According to MSDN this may happen when the window is not in the foreground, but the default is 1 since a long time (which means no retries), so it should be ok. I've found no problems during testing it on Windows 7 and wine, so this was probably only the case with some old Windows versions. Signed-off-by: Kővágó, Zoltán <DirtY.iCE.hu@gmail.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
		
			
				
	
	
		
			279 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			279 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * QEMU DirectSound audio driver header
 | 
						|
 *
 | 
						|
 * Copyright (c) 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.
 | 
						|
 */
 | 
						|
#ifdef DSBTYPE_IN
 | 
						|
#define NAME "capture buffer"
 | 
						|
#define NAME2 "DirectSoundCapture"
 | 
						|
#define TYPE in
 | 
						|
#define IFACE IDirectSoundCaptureBuffer
 | 
						|
#define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
 | 
						|
#define FIELD dsound_capture_buffer
 | 
						|
#define FIELD2 dsound_capture
 | 
						|
#else
 | 
						|
#define NAME "playback buffer"
 | 
						|
#define NAME2 "DirectSound"
 | 
						|
#define TYPE out
 | 
						|
#define IFACE IDirectSoundBuffer
 | 
						|
#define BUFPTR LPDIRECTSOUNDBUFFER
 | 
						|
#define FIELD dsound_buffer
 | 
						|
#define FIELD2 dsound
 | 
						|
#endif
 | 
						|
 | 
						|
static int glue (dsound_unlock_, TYPE) (
 | 
						|
    BUFPTR buf,
 | 
						|
    LPVOID p1,
 | 
						|
    LPVOID p2,
 | 
						|
    DWORD blen1,
 | 
						|
    DWORD blen2
 | 
						|
    )
 | 
						|
{
 | 
						|
    HRESULT hr;
 | 
						|
 | 
						|
    hr = glue (IFACE, _Unlock) (buf, p1, blen1, p2, blen2);
 | 
						|
    if (FAILED (hr)) {
 | 
						|
        dsound_logerr (hr, "Could not unlock " NAME "\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int glue (dsound_lock_, TYPE) (
 | 
						|
    BUFPTR buf,
 | 
						|
    struct audio_pcm_info *info,
 | 
						|
    DWORD pos,
 | 
						|
    DWORD len,
 | 
						|
    LPVOID *p1p,
 | 
						|
    LPVOID *p2p,
 | 
						|
    DWORD *blen1p,
 | 
						|
    DWORD *blen2p,
 | 
						|
    int entire,
 | 
						|
    dsound *s
 | 
						|
    )
 | 
						|
{
 | 
						|
    HRESULT hr;
 | 
						|
    LPVOID p1 = NULL, p2 = NULL;
 | 
						|
    DWORD blen1 = 0, blen2 = 0;
 | 
						|
    DWORD flag;
 | 
						|
 | 
						|
#ifdef DSBTYPE_IN
 | 
						|
    flag = entire ? DSCBLOCK_ENTIREBUFFER : 0;
 | 
						|
#else
 | 
						|
    flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
 | 
						|
#endif
 | 
						|
    hr = glue(IFACE, _Lock)(buf, pos, len, &p1, &blen1, &p2, &blen2, flag);
 | 
						|
 | 
						|
    if (FAILED (hr)) {
 | 
						|
#ifndef DSBTYPE_IN
 | 
						|
        if (hr == DSERR_BUFFERLOST) {
 | 
						|
            if (glue (dsound_restore_, TYPE) (buf, s)) {
 | 
						|
                dsound_logerr (hr, "Could not lock " NAME "\n");
 | 
						|
            }
 | 
						|
            goto fail;
 | 
						|
        }
 | 
						|
#endif
 | 
						|
        dsound_logerr (hr, "Could not lock " NAME "\n");
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
 | 
						|
        dolog ("DirectSound returned misaligned buffer %ld %ld\n",
 | 
						|
               blen1, blen2);
 | 
						|
        glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
 | 
						|
        goto fail;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!p1 && blen1) {
 | 
						|
        dolog ("warning: !p1 && blen1=%ld\n", blen1);
 | 
						|
        blen1 = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!p2 && blen2) {
 | 
						|
        dolog ("warning: !p2 && blen2=%ld\n", blen2);
 | 
						|
        blen2 = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    *p1p = p1;
 | 
						|
    *p2p = p2;
 | 
						|
    *blen1p = blen1;
 | 
						|
    *blen2p = blen2;
 | 
						|
    return 0;
 | 
						|
 | 
						|
 fail:
 | 
						|
    *p1p = NULL - 1;
 | 
						|
    *p2p = NULL - 1;
 | 
						|
    *blen1p = -1;
 | 
						|
    *blen2p = -1;
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
#ifdef DSBTYPE_IN
 | 
						|
static void dsound_fini_in (HWVoiceIn *hw)
 | 
						|
#else
 | 
						|
static void dsound_fini_out (HWVoiceOut *hw)
 | 
						|
#endif
 | 
						|
{
 | 
						|
    HRESULT hr;
 | 
						|
#ifdef DSBTYPE_IN
 | 
						|
    DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
 | 
						|
#else
 | 
						|
    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
 | 
						|
#endif
 | 
						|
 | 
						|
    if (ds->FIELD) {
 | 
						|
        hr = glue (IFACE, _Stop) (ds->FIELD);
 | 
						|
        if (FAILED (hr)) {
 | 
						|
            dsound_logerr (hr, "Could not stop " NAME "\n");
 | 
						|
        }
 | 
						|
 | 
						|
        hr = glue (IFACE, _Release) (ds->FIELD);
 | 
						|
        if (FAILED (hr)) {
 | 
						|
            dsound_logerr (hr, "Could not release " NAME "\n");
 | 
						|
        }
 | 
						|
        ds->FIELD = NULL;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#ifdef DSBTYPE_IN
 | 
						|
static int dsound_init_in(HWVoiceIn *hw, struct audsettings *as,
 | 
						|
                          void *drv_opaque)
 | 
						|
#else
 | 
						|
static int dsound_init_out(HWVoiceOut *hw, struct audsettings *as,
 | 
						|
                           void *drv_opaque)
 | 
						|
#endif
 | 
						|
{
 | 
						|
    int err;
 | 
						|
    HRESULT hr;
 | 
						|
    dsound *s = drv_opaque;
 | 
						|
    WAVEFORMATEX wfx;
 | 
						|
    struct audsettings obt_as;
 | 
						|
    DSoundConf *conf = &s->conf;
 | 
						|
#ifdef DSBTYPE_IN
 | 
						|
    const char *typ = "ADC";
 | 
						|
    DSoundVoiceIn *ds = (DSoundVoiceIn *) hw;
 | 
						|
    DSCBUFFERDESC bd;
 | 
						|
    DSCBCAPS bc;
 | 
						|
#else
 | 
						|
    const char *typ = "DAC";
 | 
						|
    DSoundVoiceOut *ds = (DSoundVoiceOut *) hw;
 | 
						|
    DSBUFFERDESC bd;
 | 
						|
    DSBCAPS bc;
 | 
						|
#endif
 | 
						|
 | 
						|
    if (!s->FIELD2) {
 | 
						|
        dolog ("Attempt to initialize voice without " NAME2 " object\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    err = waveformat_from_audio_settings (&wfx, as);
 | 
						|
    if (err) {
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    memset (&bd, 0, sizeof (bd));
 | 
						|
    bd.dwSize = sizeof (bd);
 | 
						|
    bd.lpwfxFormat = &wfx;
 | 
						|
#ifdef DSBTYPE_IN
 | 
						|
    bd.dwBufferBytes = conf->bufsize_in;
 | 
						|
    hr = IDirectSoundCapture_CreateCaptureBuffer (
 | 
						|
        s->dsound_capture,
 | 
						|
        &bd,
 | 
						|
        &ds->dsound_capture_buffer,
 | 
						|
        NULL
 | 
						|
        );
 | 
						|
#else
 | 
						|
    bd.dwFlags = DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2;
 | 
						|
    bd.dwBufferBytes = conf->bufsize_out;
 | 
						|
    hr = IDirectSound_CreateSoundBuffer (
 | 
						|
        s->dsound,
 | 
						|
        &bd,
 | 
						|
        &ds->dsound_buffer,
 | 
						|
        NULL
 | 
						|
        );
 | 
						|
#endif
 | 
						|
 | 
						|
    if (FAILED (hr)) {
 | 
						|
        dsound_logerr2 (hr, typ, "Could not create " NAME "\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    hr = glue (IFACE, _GetFormat) (ds->FIELD, &wfx, sizeof (wfx), NULL);
 | 
						|
    if (FAILED (hr)) {
 | 
						|
        dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
 | 
						|
        goto fail0;
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef DEBUG_DSOUND
 | 
						|
    dolog (NAME "\n");
 | 
						|
    print_wave_format (&wfx);
 | 
						|
#endif
 | 
						|
 | 
						|
    memset (&bc, 0, sizeof (bc));
 | 
						|
    bc.dwSize = sizeof (bc);
 | 
						|
 | 
						|
    hr = glue (IFACE, _GetCaps) (ds->FIELD, &bc);
 | 
						|
    if (FAILED (hr)) {
 | 
						|
        dsound_logerr2 (hr, typ, "Could not get " NAME " format\n");
 | 
						|
        goto fail0;
 | 
						|
    }
 | 
						|
 | 
						|
    err = waveformat_to_audio_settings (&wfx, &obt_as);
 | 
						|
    if (err) {
 | 
						|
        goto fail0;
 | 
						|
    }
 | 
						|
 | 
						|
    ds->first_time = 1;
 | 
						|
    obt_as.endianness = 0;
 | 
						|
    audio_pcm_init_info (&hw->info, &obt_as);
 | 
						|
 | 
						|
    if (bc.dwBufferBytes & hw->info.align) {
 | 
						|
        dolog (
 | 
						|
            "GetCaps returned misaligned buffer size %ld, alignment %d\n",
 | 
						|
            bc.dwBufferBytes, hw->info.align + 1
 | 
						|
            );
 | 
						|
    }
 | 
						|
    hw->samples = bc.dwBufferBytes >> hw->info.shift;
 | 
						|
    ds->s = s;
 | 
						|
 | 
						|
#ifdef DEBUG_DSOUND
 | 
						|
    dolog ("caps %ld, desc %ld\n",
 | 
						|
           bc.dwBufferBytes, bd.dwBufferBytes);
 | 
						|
 | 
						|
    dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
 | 
						|
           hw->bufsize, settings.freq, settings.nchannels, settings.fmt);
 | 
						|
#endif
 | 
						|
    return 0;
 | 
						|
 | 
						|
 fail0:
 | 
						|
    glue (dsound_fini_, TYPE) (hw);
 | 
						|
    return -1;
 | 
						|
}
 | 
						|
 | 
						|
#undef NAME
 | 
						|
#undef NAME2
 | 
						|
#undef TYPE
 | 
						|
#undef IFACE
 | 
						|
#undef BUFPTR
 | 
						|
#undef FIELD
 | 
						|
#undef FIELD2
 |