All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Volker Rümelin" <vr_qemu@t-online.de>
To: Gerd Hoffmann <kraxel@redhat.com>
Cc: QEMU <qemu-devel@nongnu.org>, "Zoltán Kővágó" <dirty.ice.hu@gmail.com>
Subject: [PATCH 07/23] sdlaudio: replace legacy functions with modern ones
Date: Sun, 10 Jan 2021 11:02:23 +0100	[thread overview]
Message-ID: <20210110100239.27588-7-vr_qemu@t-online.de> (raw)
In-Reply-To: <9315afe5-5958-c0b4-ea1e-14769511a9d5@t-online.de>

With the modern audio functions it's possible to add new
features like audio recording.

As a side effect this patch fixes a bug where SDL2 can't be used
on Windows. This bug was reported on the qemu-devel mailing list at

https://lists.nongnu.org/archive/html/qemu-devel/2020-01/msg04043.html

Signed-off-by: Volker Rümelin <vr_qemu@t-online.de>
---
 audio/sdlaudio.c | 107 ++++++++++++++++++++++-------------------------
 1 file changed, 50 insertions(+), 57 deletions(-)

diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index 01ae4c600e..47968c5020 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -41,15 +41,11 @@
 
 typedef struct SDLVoiceOut {
     HWVoiceOut hw;
-} SDLVoiceOut;
-
-static struct SDLAudioState {
     int exit;
     int initialized;
-    bool driver_created;
     Audiodev *dev;
-} glob_sdl;
-typedef struct SDLAudioState SDLAudioState;
+    SDL_AudioDeviceID devid;
+} SDLVoiceOut;
 
 static void GCC_FMT_ATTR (1, 2) sdl_logerr (const char *fmt, ...)
 {
@@ -155,9 +151,10 @@ static int sdl_to_audfmt(int sdlfmt, AudioFormat *fmt, int *endianness)
     return 0;
 }
 
-static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
+static SDL_AudioDeviceID sdl_open(SDL_AudioSpec *req, SDL_AudioSpec *obt,
+                                  int rec)
 {
-    int status;
+    SDL_AudioDeviceID devid;
 #ifndef _WIN32
     int err;
     sigset_t new, old;
@@ -166,18 +163,19 @@ static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
     err = sigfillset (&new);
     if (err) {
         dolog ("sdl_open: sigfillset failed: %s\n", strerror (errno));
-        return -1;
+        return 0;
     }
     err = pthread_sigmask (SIG_BLOCK, &new, &old);
     if (err) {
         dolog ("sdl_open: pthread_sigmask failed: %s\n", strerror (err));
-        return -1;
+        return 0;
     }
 #endif
 
-    status = SDL_OpenAudio (req, obt);
-    if (status) {
-        sdl_logerr ("SDL_OpenAudio failed\n");
+    devid = SDL_OpenAudioDevice(NULL, rec, req, obt, 0);
+    if (!devid) {
+        sdl_logerr("SDL_OpenAudioDevice for %s failed\n",
+                   rec ? "recording" : "playback");
     }
 
 #ifndef _WIN32
@@ -190,30 +188,32 @@ static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
         exit (EXIT_FAILURE);
     }
 #endif
-    return status;
+    return devid;
 }
 
-static void sdl_close (SDLAudioState *s)
+static void sdl_close_out(SDLVoiceOut *sdl)
 {
-    if (s->initialized) {
-        SDL_LockAudio();
-        s->exit = 1;
-        SDL_UnlockAudio();
-        SDL_PauseAudio (1);
-        SDL_CloseAudio ();
-        s->initialized = 0;
+    if (sdl->initialized) {
+        SDL_LockAudioDevice(sdl->devid);
+        sdl->exit = 1;
+        SDL_UnlockAudioDevice(sdl->devid);
+        SDL_PauseAudioDevice(sdl->devid, 1);
+        sdl->initialized = 0;
+    }
+    if (sdl->devid) {
+        SDL_CloseAudioDevice(sdl->devid);
+        sdl->devid = 0;
     }
 }
 
-static void sdl_callback (void *opaque, Uint8 *buf, int len)
+static void sdl_callback_out(void *opaque, Uint8 *buf, int len)
 {
     SDLVoiceOut *sdl = opaque;
-    SDLAudioState *s = &glob_sdl;
     HWVoiceOut *hw = &sdl->hw;
 
-    if (!s->exit) {
+    if (!sdl->exit) {
 
-        /* dolog("callback: len=%d avail=%zu\n", len, hw->pending_emul); */
+        /* dolog("callback_out: len=%d avail=%zu\n", len, hw->pending_emul); */
 
         while (hw->pending_emul && len) {
             size_t write_len;
@@ -240,43 +240,44 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
     }
 }
 
-#define SDL_WRAPPER_FUNC(name, ret_type, args_decl, args)      \
+#define SDL_WRAPPER_FUNC(name, ret_type, args_decl, args, dir) \
     static ret_type glue(sdl_, name)args_decl                  \
     {                                                          \
         ret_type ret;                                          \
+        glue(SDLVoice, dir) *sdl = (glue(SDLVoice, dir) *)hw;  \
                                                                \
-        SDL_LockAudio();                                       \
+        SDL_LockAudioDevice(sdl->devid);                       \
         ret = glue(audio_generic_, name)args;                  \
-        SDL_UnlockAudio();                                     \
+        SDL_UnlockAudioDevice(sdl->devid);                     \
                                                                \
         return ret;                                            \
     }
 
 SDL_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
-                 (hw, size))
+                 (hw, size), Out)
 SDL_WRAPPER_FUNC(put_buffer_out, size_t,
-                 (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size))
+                 (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size), Out)
 SDL_WRAPPER_FUNC(write, size_t,
-                 (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size))
+                 (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size), Out)
 #undef SDL_WRAPPER_FUNC
 
-static void sdl_fini_out (HWVoiceOut *hw)
+static void sdl_fini_out(HWVoiceOut *hw)
 {
-    (void) hw;
+    SDLVoiceOut *sdl = (SDLVoiceOut *)hw;
 
-    sdl_close (&glob_sdl);
+    sdl_close_out(sdl);
 }
 
 static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,
                         void *drv_opaque)
 {
-    SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
-    SDLAudioState *s = &glob_sdl;
+    SDLVoiceOut *sdl = (SDLVoiceOut *)hw;
     SDL_AudioSpec req, obt;
     int endianness;
     int err;
     AudioFormat effective_fmt;
-    AudiodevSdlPerDirectionOptions *spdo = s->dev->u.sdl.out;
+    Audiodev *dev = drv_opaque;
+    AudiodevSdlPerDirectionOptions *spdo = dev->u.sdl.out;
     struct audsettings obt_as;
 
     req.freq = as->freq;
@@ -288,16 +289,18 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,
      */
     req.samples = audio_buffer_samples(
         qapi_AudiodevSdlPerDirectionOptions_base(spdo), as, 11610);
-    req.callback = sdl_callback;
+    req.callback = sdl_callback_out;
     req.userdata = sdl;
 
-    if (sdl_open (&req, &obt)) {
+    sdl->dev = dev;
+    sdl->devid = sdl_open(&req, &obt, 0);
+    if (!sdl->devid) {
         return -1;
     }
 
     err = sdl_to_audfmt(obt.format, &effective_fmt, &endianness);
     if (err) {
-        sdl_close (s);
+        sdl_close_out(sdl);
         return -1;
     }
 
@@ -310,41 +313,31 @@ static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,
     hw->samples = (spdo->has_buffer_count ? spdo->buffer_count : 4) *
         obt.samples;
 
-    s->initialized = 1;
-    s->exit = 0;
+    sdl->initialized = 1;
+    sdl->exit = 0;
     return 0;
 }
 
 static void sdl_enable_out(HWVoiceOut *hw, bool enable)
 {
-    SDL_PauseAudio(!enable);
+    SDLVoiceOut *sdl = (SDLVoiceOut *)hw;
+
+    SDL_PauseAudioDevice(sdl->devid, !enable);
 }
 
 static void *sdl_audio_init(Audiodev *dev)
 {
-    SDLAudioState *s = &glob_sdl;
-    if (s->driver_created) {
-        sdl_logerr("Can't create multiple sdl backends\n");
-        return NULL;
-    }
-
     if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
         sdl_logerr ("SDL failed to initialize audio subsystem\n");
         return NULL;
     }
 
-    s->driver_created = true;
-    s->dev = dev;
-    return s;
+    return dev;
 }
 
 static void sdl_audio_fini (void *opaque)
 {
-    SDLAudioState *s = opaque;
-    sdl_close (s);
     SDL_QuitSubSystem (SDL_INIT_AUDIO);
-    s->driver_created = false;
-    s->dev = NULL;
 }
 
 static struct audio_pcm_ops sdl_pcm_ops = {
-- 
2.26.2



  parent reply	other threads:[~2021-01-10 10:08 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-10 10:01 [PATCH 00/23] next round of audio patches Volker Rümelin
2021-01-10 10:02 ` [PATCH 01/23] sdlaudio: remove leftover SDL1.2 code Volker Rümelin
2021-01-14 15:28   ` Thomas Huth
2021-01-10 10:02 ` [PATCH 02/23] audio: fix bit-rotted code Volker Rümelin
2021-01-14 14:32   ` Gerd Hoffmann
2021-01-31 17:13     ` Volker Rümelin
2021-01-10 10:02 ` [PATCH 03/23] sdlaudio: add -audiodev sdl,out.buffer-count option Volker Rümelin
2021-01-14 14:27   ` [PATCH 03/23] sdlaudio: add -audiodev sdl, out.buffer-count option Gerd Hoffmann
2021-01-31 17:30     ` Volker Rümelin
2021-01-15  8:39   ` Markus Armbruster
2021-01-10 10:02 ` [PATCH 04/23] sdlaudio: don't start playback in init routine Volker Rümelin
2021-01-15  6:28   ` Thomas Huth
2021-01-10 10:02 ` [PATCH 05/23] sdlaudio: always clear the sample buffer Volker Rümelin
2021-01-15  6:31   ` Thomas Huth
2021-01-10 10:02 ` [PATCH 06/23] sdlaudio: fill remaining sample buffer with silence Volker Rümelin
2021-01-14 16:58   ` Thomas Huth
2021-01-17  9:41     ` Volker Rümelin
2021-01-10 10:02 ` Volker Rümelin [this message]
2021-01-15  7:04   ` [PATCH 07/23] sdlaudio: replace legacy functions with modern ones Thomas Huth
2021-01-10 10:02 ` [PATCH 08/23] audio: split pcm_ops function get_buffer_in Volker Rümelin
2021-01-10 10:02 ` [PATCH 09/23] sdlaudio: add recording functions Volker Rümelin
2021-01-10 10:02 ` [PATCH 10/23] audio: break generic buffer dependency on mixing-engine Volker Rümelin
2021-01-10 10:02 ` [PATCH 11/23] sdlaudio: enable (in|out).mixing-engine=off Volker Rümelin
2021-01-10 10:02 ` [PATCH 12/23] audio: remove remaining unused plive code Volker Rümelin
2021-01-10 10:02 ` [PATCH 13/23] paaudio: avoid to clip samples multiple times Volker Rümelin
2021-01-10 10:02 ` [PATCH 14/23] paaudio: wait for PA_STREAM_READY in qpa_write() Volker Rümelin
2021-01-10 10:02 ` [PATCH 15/23] paaudio: wait until the playback stream is ready Volker Rümelin
2021-01-10 10:02 ` [PATCH 16/23] paaudio: remove unneeded code Volker Rümelin
2021-01-10 10:02 ` [PATCH 17/23] paaudio: comment bugs in functions qpa_init_* Volker Rümelin
2021-01-10 10:02 ` [PATCH 18/23] paaudio: limit minreq to 75% of audio timer_rate Volker Rümelin
2021-01-10 10:02 ` [PATCH 19/23] paaudio: send recorded data in smaller chunks Volker Rümelin
2021-01-10 10:02 ` [PATCH 20/23] dsoundaudio: replace GetForegroundWindow() Volker Rümelin
2021-01-10 10:02 ` [PATCH 21/23] dsoundaudio: rename dsound_open() Volker Rümelin
2021-01-10 10:02 ` [PATCH 22/23] dsoundaudio: enable f32 audio sample format Volker Rümelin
2021-01-10 10:02 ` [PATCH 23/23] dsoundaudio: fix log message Volker Rümelin
2021-01-10 10:24 ` [PATCH 00/23] next round of audio patches no-reply
2021-01-10 23:09   ` Volker Rümelin
2021-01-14 14:36 ` Gerd Hoffmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210110100239.27588-7-vr_qemu@t-online.de \
    --to=vr_qemu@t-online.de \
    --cc=dirty.ice.hu@gmail.com \
    --cc=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.