Annotation of qemu/audio/sdlaudio.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * QEMU SDL audio output driver
        !             3:  * 
        !             4:  * Copyright (c) 2004 Vassili Karpov (malc)
        !             5:  * 
        !             6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             7:  * of this software and associated documentation files (the "Software"), to deal
        !             8:  * in the Software without restriction, including without limitation the rights
        !             9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            10:  * copies of the Software, and to permit persons to whom the Software is
        !            11:  * furnished to do so, subject to the following conditions:
        !            12:  *
        !            13:  * The above copyright notice and this permission notice shall be included in
        !            14:  * all copies or substantial portions of the Software.
        !            15:  *
        !            16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
        !            19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            22:  * THE SOFTWARE.
        !            23:  */
        !            24: #include <SDL.h>
        !            25: #include <SDL_thread.h>
        !            26: #include "vl.h"
        !            27: 
        !            28: #include "audio/audio_int.h"
        !            29: 
        !            30: typedef struct SDLVoice {
        !            31:     HWVoice hw;
        !            32: } SDLVoice;
        !            33: 
        !            34: #define dolog(...) AUD_log ("sdl", __VA_ARGS__)
        !            35: #ifdef DEBUG
        !            36: #define ldebug(...) dolog (__VA_ARGS__)
        !            37: #else
        !            38: #define ldebug(...)
        !            39: #endif
        !            40: 
        !            41: #define QC_SDL_SAMPLES "QEMU_SDL_SAMPLES"
        !            42: 
        !            43: #define errstr() SDL_GetError ()
        !            44: 
        !            45: static struct {
        !            46:     int nb_samples;
        !            47: } conf = {
        !            48:     1024
        !            49: };
        !            50: 
        !            51: struct SDLAudioState {
        !            52:     int exit;
        !            53:     SDL_mutex *mutex;
        !            54:     SDL_sem *sem;
        !            55:     int initialized;
        !            56: } glob_sdl;
        !            57: typedef struct SDLAudioState SDLAudioState;
        !            58: 
        !            59: static void sdl_hw_run (HWVoice *hw)
        !            60: {
        !            61:     (void) hw;
        !            62: }
        !            63: 
        !            64: static int sdl_lock (SDLAudioState *s)
        !            65: {
        !            66:     if (SDL_LockMutex (s->mutex)) {
        !            67:         dolog ("SDL_LockMutex failed\nReason: %s\n", errstr ());
        !            68:         return -1;
        !            69:     }
        !            70:     return 0;
        !            71: }
        !            72: 
        !            73: static int sdl_unlock (SDLAudioState *s)
        !            74: {
        !            75:     if (SDL_UnlockMutex (s->mutex)) {
        !            76:         dolog ("SDL_UnlockMutex failed\nReason: %s\n", errstr ());
        !            77:         return -1;
        !            78:     }
        !            79:     return 0;
        !            80: }
        !            81: 
        !            82: static int sdl_post (SDLAudioState *s)
        !            83: {
        !            84:     if (SDL_SemPost (s->sem)) {
        !            85:         dolog ("SDL_SemPost failed\nReason: %s\n", errstr ());
        !            86:         return -1;
        !            87:     }
        !            88:     return 0;
        !            89: }
        !            90: 
        !            91: static int sdl_wait (SDLAudioState *s)
        !            92: {
        !            93:     if (SDL_SemWait (s->sem)) {
        !            94:         dolog ("SDL_SemWait failed\nReason: %s\n", errstr ());
        !            95:         return -1;
        !            96:     }
        !            97:     return 0;
        !            98: }
        !            99: 
        !           100: static int sdl_unlock_and_post (SDLAudioState *s)
        !           101: {
        !           102:     if (sdl_unlock (s))
        !           103:         return -1;
        !           104: 
        !           105:     return sdl_post (s);
        !           106: }
        !           107: 
        !           108: static int sdl_hw_write (SWVoice *sw, void *buf, int len)
        !           109: {
        !           110:     int ret;
        !           111:     SDLAudioState *s = &glob_sdl;
        !           112:     sdl_lock (s);
        !           113:     ret = pcm_hw_write (sw, buf, len);
        !           114:     sdl_unlock_and_post (s);
        !           115:     return ret;
        !           116: }
        !           117: 
        !           118: static int AUD_to_sdlfmt (audfmt_e fmt, int *shift)
        !           119: {
        !           120:     *shift = 0;
        !           121:     switch (fmt) {
        !           122:     case AUD_FMT_S8: return AUDIO_S8;
        !           123:     case AUD_FMT_U8: return AUDIO_U8;
        !           124:     case AUD_FMT_S16: *shift = 1; return AUDIO_S16LSB;
        !           125:     case AUD_FMT_U16: *shift = 1; return AUDIO_U16LSB;
        !           126:     default:
        !           127:         dolog ("Internal logic error: Bad audio format %d\nAborting\n", fmt);
        !           128:         exit (EXIT_FAILURE);
        !           129:     }
        !           130: }
        !           131: 
        !           132: static int sdl_to_audfmt (int fmt)
        !           133: {
        !           134:     switch (fmt) {
        !           135:     case AUDIO_S8: return AUD_FMT_S8;
        !           136:     case AUDIO_U8: return AUD_FMT_U8;
        !           137:     case AUDIO_S16LSB: return AUD_FMT_S16;
        !           138:     case AUDIO_U16LSB: return AUD_FMT_U16;
        !           139:     default:
        !           140:         dolog ("Internal logic error: Unrecognized SDL audio format %d\n"
        !           141:                "Aborting\n", fmt);
        !           142:         exit (EXIT_FAILURE);
        !           143:     }
        !           144: }
        !           145: 
        !           146: static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
        !           147: {
        !           148:     int status;
        !           149: 
        !           150:     status = SDL_OpenAudio (req, obt);
        !           151:     if (status) {
        !           152:         dolog ("SDL_OpenAudio failed\nReason: %s\n", errstr ());
        !           153:     }
        !           154:     return status;
        !           155: }
        !           156: 
        !           157: static void sdl_close (SDLAudioState *s)
        !           158: {
        !           159:     if (s->initialized) {
        !           160:         sdl_lock (s);
        !           161:         s->exit = 1;
        !           162:         sdl_unlock_and_post (s);
        !           163:         SDL_PauseAudio (1);
        !           164:         SDL_CloseAudio ();
        !           165:         s->initialized = 0;
        !           166:     }
        !           167: }
        !           168: 
        !           169: static void sdl_callback (void *opaque, Uint8 *buf, int len)
        !           170: {
        !           171:     SDLVoice *sdl = opaque;
        !           172:     SDLAudioState *s = &glob_sdl;
        !           173:     HWVoice *hw = &sdl->hw;
        !           174:     int samples = len >> hw->shift;
        !           175: 
        !           176:     if (s->exit) {
        !           177:         return;
        !           178:     }
        !           179: 
        !           180:     while (samples) {
        !           181:         int to_mix, live, decr;
        !           182: 
        !           183:         /* dolog ("in callback samples=%d\n", samples); */
        !           184:         sdl_wait (s);
        !           185:         if (s->exit) {
        !           186:             return;
        !           187:         }
        !           188: 
        !           189:         sdl_lock (s);
        !           190:         live = pcm_hw_get_live (hw);
        !           191:         if (live <= 0)
        !           192:             goto again;
        !           193: 
        !           194:         /* dolog ("in callback live=%d\n", live); */
        !           195:         to_mix = audio_MIN (samples, live);
        !           196:         decr = to_mix;
        !           197:         while (to_mix) {
        !           198:             int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
        !           199:             st_sample_t *src = hw->mix_buf + hw->rpos;
        !           200: 
        !           201:             /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
        !           202:             hw->clip (buf, src, chunk);
        !           203:             memset (src, 0, chunk * sizeof (st_sample_t));
        !           204:             hw->rpos = (hw->rpos + chunk) % hw->samples;
        !           205:             to_mix -= chunk;
        !           206:             buf += chunk << hw->shift;
        !           207:         }
        !           208:         samples -= decr;
        !           209:         pcm_hw_dec_live (hw, decr);
        !           210: 
        !           211:     again:
        !           212:         sdl_unlock (s);
        !           213:     }
        !           214:     /* dolog ("done len=%d\n", len); */
        !           215: }
        !           216: 
        !           217: static void sdl_hw_fini (HWVoice *hw)
        !           218: {
        !           219:     ldebug ("sdl_hw_fini %d fixed=%d\n",
        !           220:              glob_sdl.initialized, audio_state.fixed_format);
        !           221:     sdl_close (&glob_sdl);
        !           222: }
        !           223: 
        !           224: static int sdl_hw_init (HWVoice *hw, int freq, int nchannels, audfmt_e fmt)
        !           225: {
        !           226:     SDLVoice *sdl = (SDLVoice *) hw;
        !           227:     SDLAudioState *s = &glob_sdl;
        !           228:     SDL_AudioSpec req, obt;
        !           229:     int shift;
        !           230: 
        !           231:     ldebug ("sdl_hw_init %d freq=%d fixed=%d\n",
        !           232:             s->initialized, freq, audio_state.fixed_format);
        !           233: 
        !           234:     if (nchannels != 2) {
        !           235:         dolog ("Bogus channel count %d\n", nchannels);
        !           236:         return -1;
        !           237:     }
        !           238: 
        !           239:     req.freq = freq;
        !           240:     req.format = AUD_to_sdlfmt (fmt, &shift);
        !           241:     req.channels = nchannels;
        !           242:     req.samples = conf.nb_samples;
        !           243:     shift <<= nchannels == 2;
        !           244: 
        !           245:     req.callback = sdl_callback;
        !           246:     req.userdata = sdl;
        !           247: 
        !           248:     if (sdl_open (&req, &obt))
        !           249:         return -1;
        !           250: 
        !           251:     hw->freq = obt.freq;
        !           252:     hw->fmt = sdl_to_audfmt (obt.format);
        !           253:     hw->nchannels = obt.channels;
        !           254:     hw->bufsize = obt.samples << shift;
        !           255: 
        !           256:     s->initialized = 1;
        !           257:     s->exit = 0;
        !           258:     SDL_PauseAudio (0);
        !           259:     return 0;
        !           260: }
        !           261: 
        !           262: static int sdl_hw_ctl (HWVoice *hw, int cmd, ...)
        !           263: {
        !           264:     (void) hw;
        !           265: 
        !           266:     switch (cmd) {
        !           267:     case VOICE_ENABLE:
        !           268:         SDL_PauseAudio (0);
        !           269:         break;
        !           270: 
        !           271:     case VOICE_DISABLE:
        !           272:         SDL_PauseAudio (1);
        !           273:         break;
        !           274:     }
        !           275:     return 0;
        !           276: }
        !           277: 
        !           278: static void *sdl_audio_init (void)
        !           279: {
        !           280:     SDLAudioState *s = &glob_sdl;
        !           281:     conf.nb_samples = audio_get_conf_int (QC_SDL_SAMPLES, conf.nb_samples);
        !           282: 
        !           283:     if (SDL_InitSubSystem (SDL_INIT_AUDIO)) {
        !           284:         dolog ("SDL failed to initialize audio subsystem\nReason: %s\n",
        !           285:                errstr ());
        !           286:         return NULL;
        !           287:     }
        !           288: 
        !           289:     s->mutex = SDL_CreateMutex ();
        !           290:     if (!s->mutex) {
        !           291:         dolog ("Failed to create SDL mutex\nReason: %s\n", errstr ());
        !           292:         SDL_QuitSubSystem (SDL_INIT_AUDIO);
        !           293:         return NULL;
        !           294:     }
        !           295: 
        !           296:     s->sem = SDL_CreateSemaphore (0);
        !           297:     if (!s->sem) {
        !           298:         dolog ("Failed to create SDL semaphore\nReason: %s\n", errstr ());
        !           299:         SDL_DestroyMutex (s->mutex);
        !           300:         SDL_QuitSubSystem (SDL_INIT_AUDIO);
        !           301:         return NULL;
        !           302:     }
        !           303: 
        !           304:     return s;
        !           305: }
        !           306: 
        !           307: static void sdl_audio_fini (void *opaque)
        !           308: {
        !           309:     SDLAudioState *s = opaque;
        !           310:     sdl_close (s);
        !           311:     SDL_DestroySemaphore (s->sem);
        !           312:     SDL_DestroyMutex (s->mutex);
        !           313:     SDL_QuitSubSystem (SDL_INIT_AUDIO);
        !           314: }
        !           315: 
        !           316: struct pcm_ops sdl_pcm_ops = {
        !           317:     sdl_hw_init,
        !           318:     sdl_hw_fini,
        !           319:     sdl_hw_run,
        !           320:     sdl_hw_write,
        !           321:     sdl_hw_ctl
        !           322: };
        !           323: 
        !           324: struct audio_output_driver sdl_output_driver = {
        !           325:     "sdl",
        !           326:     sdl_audio_init,
        !           327:     sdl_audio_fini,
        !           328:     &sdl_pcm_ops,
        !           329:     1,
        !           330:     1,
        !           331:     sizeof (SDLVoice)
        !           332: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.