]> git.proxmox.com Git - mirror_qemu.git/blobdiff - audio/sdlaudio.c
qht: QEMU's fast, resizable and scalable Hash Table
[mirror_qemu.git] / audio / sdlaudio.c
index 5d6fc24116c1d95f0e7fa121365e3e07d0fd5040..db69fe141622bc90d5f28692984332e0757554f2 100644 (file)
@@ -21,6 +21,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
+#include "qemu/osdep.h"
 #include <SDL.h>
 #include <SDL_thread.h>
 #include "qemu-common.h"
@@ -32,7 +33,6 @@
 #elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
 #include <pthread.h>
 #endif
-#include <signal.h>
 #endif
 
 #define AUDIO_CAP "sdl"
@@ -48,7 +48,7 @@ typedef struct SDLVoiceOut {
 static struct {
     int nb_samples;
 } conf = {
-    1024
+    .nb_samples = 1024
 };
 
 static struct SDLAudioState {
@@ -56,6 +56,7 @@ static struct SDLAudioState {
     SDL_mutex *mutex;
     SDL_sem *sem;
     int initialized;
+    bool driver_created;
 } glob_sdl;
 typedef struct SDLAudioState SDLAudioState;
 
@@ -115,23 +116,19 @@ static int sdl_unlock_and_post (SDLAudioState *s, const char *forfn)
     return sdl_post (s, forfn);
 }
 
-static int aud_to_sdlfmt (audfmt_e fmt, int *shift)
+static int aud_to_sdlfmt (audfmt_e fmt)
 {
     switch (fmt) {
     case AUD_FMT_S8:
-        *shift = 0;
         return AUDIO_S8;
 
     case AUD_FMT_U8:
-        *shift = 0;
         return AUDIO_U8;
 
     case AUD_FMT_S16:
-        *shift = 1;
         return AUDIO_S16LSB;
 
     case AUD_FMT_U16:
-        *shift = 1;
         return AUDIO_U16LSB;
 
     default:
@@ -143,36 +140,36 @@ static int aud_to_sdlfmt (audfmt_e fmt, int *shift)
     }
 }
 
-static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess)
+static int sdl_to_audfmt(int sdlfmt, audfmt_e *fmt, int *endianness)
 {
     switch (sdlfmt) {
     case AUDIO_S8:
-        *endianess = 0;
+        *endianness = 0;
         *fmt = AUD_FMT_S8;
         break;
 
     case AUDIO_U8:
-        *endianess = 0;
+        *endianness = 0;
         *fmt = AUD_FMT_U8;
         break;
 
     case AUDIO_S16LSB:
-        *endianess = 0;
+        *endianness = 0;
         *fmt = AUD_FMT_S16;
         break;
 
     case AUDIO_U16LSB:
-        *endianess = 0;
+        *endianness = 0;
         *fmt = AUD_FMT_U16;
         break;
 
     case AUDIO_S16MSB:
-        *endianess = 1;
+        *endianness = 1;
         *fmt = AUD_FMT_S16;
         break;
 
     case AUDIO_U16MSB:
-        *endianess = 1;
+        *endianness = 1;
         *fmt = AUD_FMT_U16;
         break;
 
@@ -188,11 +185,20 @@ static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
 {
     int status;
 #ifndef _WIN32
+    int err;
     sigset_t new, old;
 
     /* Make sure potential threads created by SDL don't hog signals.  */
-    sigfillset (&new);
-    pthread_sigmask (SIG_BLOCK, &new, &old);
+    err = sigfillset (&new);
+    if (err) {
+        dolog ("sdl_open: sigfillset failed: %s\n", strerror (errno));
+        return -1;
+    }
+    err = pthread_sigmask (SIG_BLOCK, &new, &old);
+    if (err) {
+        dolog ("sdl_open: pthread_sigmask failed: %s\n", strerror (err));
+        return -1;
+    }
 #endif
 
     status = SDL_OpenAudio (req, obt);
@@ -201,7 +207,14 @@ static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
     }
 
 #ifndef _WIN32
-    pthread_sigmask (SIG_SETMASK, &old, 0);
+    err = pthread_sigmask (SIG_SETMASK, &old, NULL);
+    if (err) {
+        dolog ("sdl_open: pthread_sigmask (restore) failed: %s\n",
+               strerror (errno));
+        /* We have failed to restore original signal mask, all bets are off,
+           so exit the process */
+        exit (EXIT_FAILURE);
+    }
 #endif
     return status;
 }
@@ -282,18 +295,16 @@ static int sdl_write_out (SWVoiceOut *sw, void *buf, int len)
     return audio_pcm_sw_write (sw, buf, len);
 }
 
-static int sdl_run_out (HWVoiceOut *hw)
+static int sdl_run_out (HWVoiceOut *hw, int live)
 {
-    int decr, live;
+    int decr;
     SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
     SDLAudioState *s = &glob_sdl;
 
-    if (sdl_lock (s, "sdl_callback")) {
+    if (sdl_lock (s, "sdl_run_out")) {
         return 0;
     }
 
-    live = audio_pcm_hw_get_live_out (hw);
-
     if (sdl->decr > live) {
         ldebug ("sdl->decr %d live %d sdl->live %d\n",
                 sdl->decr,
@@ -308,10 +319,10 @@ static int sdl_run_out (HWVoiceOut *hw)
     hw->rpos = sdl->rpos;
 
     if (sdl->live > 0) {
-        sdl_unlock_and_post (s, "sdl_callback");
+        sdl_unlock_and_post (s, "sdl_run_out");
     }
     else {
-        sdl_unlock (s, "sdl_callback");
+        sdl_unlock (s, "sdl_run_out");
     }
     return decr;
 }
@@ -323,21 +334,19 @@ static void sdl_fini_out (HWVoiceOut *hw)
     sdl_close (&glob_sdl);
 }
 
-static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
+static int sdl_init_out(HWVoiceOut *hw, struct audsettings *as,
+                        void *drv_opaque)
 {
     SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
     SDLAudioState *s = &glob_sdl;
     SDL_AudioSpec req, obt;
-    int shift;
-    int endianess;
+    int endianness;
     int err;
     audfmt_e effective_fmt;
     struct audsettings obt_as;
 
-    shift <<= as->nchannels == 2;
-
     req.freq = as->freq;
-    req.format = aud_to_sdlfmt (as->fmt, &shift);
+    req.format = aud_to_sdlfmt (as->fmt);
     req.channels = as->nchannels;
     req.samples = conf.nb_samples;
     req.callback = sdl_callback;
@@ -347,7 +356,7 @@ static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
         return -1;
     }
 
-    err = sdl_to_audfmt (obt.format, &effective_fmt, &endianess);
+    err = sdl_to_audfmt(obt.format, &effective_fmt, &endianness);
     if (err) {
         sdl_close (s);
         return -1;
@@ -356,7 +365,7 @@ 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 = endianess;
+    obt_as.endianness = endianness;
 
     audio_pcm_init_info (&hw->info, &obt_as);
     hw->samples = obt.samples;
@@ -386,6 +395,10 @@ static int sdl_ctl_out (HWVoiceOut *hw, int cmd, ...)
 static void *sdl_audio_init (void)
 {
     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");
@@ -407,6 +420,7 @@ static void *sdl_audio_init (void)
         return NULL;
     }
 
+    s->driver_created = true;
     return s;
 }
 
@@ -417,38 +431,37 @@ static void sdl_audio_fini (void *opaque)
     SDL_DestroySemaphore (s->sem);
     SDL_DestroyMutex (s->mutex);
     SDL_QuitSubSystem (SDL_INIT_AUDIO);
+    s->driver_created = false;
 }
 
 static struct audio_option sdl_options[] = {
-    {"SAMPLES", AUD_OPT_INT, &conf.nb_samples,
-     "Size of SDL buffer in samples", NULL, 0},
-    {NULL, 0, NULL, NULL, NULL, 0}
+    {
+        .name  = "SAMPLES",
+        .tag   = AUD_OPT_INT,
+        .valp  = &conf.nb_samples,
+        .descr = "Size of SDL buffer in samples"
+    },
+    { /* End of list */ }
 };
 
 static struct audio_pcm_ops sdl_pcm_ops = {
-    sdl_init_out,
-    sdl_fini_out,
-    sdl_run_out,
-    sdl_write_out,
-    sdl_ctl_out,
-
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL
+    .init_out = sdl_init_out,
+    .fini_out = sdl_fini_out,
+    .run_out  = sdl_run_out,
+    .write    = sdl_write_out,
+    .ctl_out  = sdl_ctl_out,
 };
 
 struct audio_driver sdl_audio_driver = {
-    INIT_FIELD (name           = ) "sdl",
-    INIT_FIELD (descr          = ) "SDL http://www.libsdl.org",
-    INIT_FIELD (options        = ) sdl_options,
-    INIT_FIELD (init           = ) sdl_audio_init,
-    INIT_FIELD (fini           = ) sdl_audio_fini,
-    INIT_FIELD (pcm_ops        = ) &sdl_pcm_ops,
-    INIT_FIELD (can_be_default = ) 1,
-    INIT_FIELD (max_voices_out = ) 1,
-    INIT_FIELD (max_voices_in  = ) 0,
-    INIT_FIELD (voice_size_out = ) sizeof (SDLVoiceOut),
-    INIT_FIELD (voice_size_in  = ) 0
+    .name           = "sdl",
+    .descr          = "SDL http://www.libsdl.org",
+    .options        = sdl_options,
+    .init           = sdl_audio_init,
+    .fini           = sdl_audio_fini,
+    .pcm_ops        = &sdl_pcm_ops,
+    .can_be_default = 1,
+    .max_voices_out = 1,
+    .max_voices_in  = 0,
+    .voice_size_out = sizeof (SDLVoiceOut),
+    .voice_size_in  = 0
 };