Esempio n. 1
0
/***************************************************************************
 * DirectSoundEnumerateW [DSOUND.3]
 *
 * Enumerate all DirectSound drivers installed in the system
 *
 * PARAMS
 *    lpDSEnumCallback  [I] Address of callback function.
 *    lpContext         [I] Address of user defined context passed to callback function.
 *
 * RETURNS
 *    Success: DS_OK
 *    Failure: DSERR_INVALIDPARAM
 */
HRESULT WINAPI DirectSoundEnumerateW(
	LPDSENUMCALLBACKW lpDSEnumCallback,
	LPVOID lpContext )
{
    unsigned devs, wod;
    DSDRIVERDESC desc;
    GUID guid;
    int err;
    WCHAR wDesc[MAXPNAMELEN];
    WCHAR wName[MAXPNAMELEN];

    TRACE("lpDSEnumCallback = %p, lpContext = %p\n",
	lpDSEnumCallback, lpContext);

    if (lpDSEnumCallback == NULL) {
	WARN("invalid parameter: lpDSEnumCallback == NULL\n");
	return DSERR_INVALIDPARAM;
    }

    setup_dsound_options();

    devs = waveOutGetNumDevs();
    if (devs > 0) {
	if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) {
            static const WCHAR empty[] = { 0 };
	    for (wod = 0; wod < devs; ++wod) {
                if (IsEqualGUID( &guid, &DSOUND_renderer_guids[wod] ) ) {
                    err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
                    if (err == DS_OK) {
                        TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n",
                              "Primary Sound Driver",desc.szDrvname,lpContext);
                        MultiByteToWideChar( CP_ACP, 0, "Primary Sound Driver", -1,
                                             wDesc, sizeof(wDesc)/sizeof(WCHAR) );
                        if (lpDSEnumCallback(NULL, wDesc, empty, lpContext) == FALSE)
                            return DS_OK;
		    }
		}
	    }
	}
    }

    for (wod = 0; wod < devs; ++wod) {
        err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,ds_hw_accel));
	if (err == DS_OK) {
            TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n",
                  debugstr_guid(&DSOUND_renderer_guids[wod]),desc.szDesc,desc.szDrvname,lpContext);
            MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1,
                                 wDesc, sizeof(wDesc)/sizeof(WCHAR) );
            wDesc[(sizeof(wDesc)/sizeof(WCHAR)) - 1] = '\0';

            MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1,
                                 wName, sizeof(wName)/sizeof(WCHAR) );
            wName[(sizeof(wName)/sizeof(WCHAR)) - 1] = '\0';

            if (lpDSEnumCallback(&DSOUND_renderer_guids[wod], wDesc, wName, lpContext) == FALSE)
                return DS_OK;
	}
    }
    return DS_OK;
}
Esempio n. 2
0
HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device)
{
    HRESULT err = DS_OK;
    TRACE("(%p)\n", device);

    err = mmErr(waveOutRestart(device->hwo));
    if (err != DS_OK)
        WARN("waveOutRestart failed\n");

    return err;
}
Esempio n. 3
0
HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device)
{
	HRESULT err = DS_OK;
	TRACE("(%p)\n", device);

	if (device->hwbuf) {
		err = IDsDriverBuffer_Play(device->hwbuf, 0, 0, DSBPLAY_LOOPING);
		if (err != DS_OK)
			WARN("IDsDriverBuffer_Play failed\n");
	} else {
		err = mmErr(waveOutRestart(device->hwo));
		if (err != DS_OK)
			WARN("waveOutRestart failed\n");
	}

	return err;
}
Esempio n. 4
0
HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device)
{
    HRESULT err = DS_OK;
    TRACE("(%p)\n", device);

    /* don't call the wave system with the lock set */
    LeaveCriticalSection(&(device->mixlock));

    err = mmErr(waveOutPause(device->hwo));

    EnterCriticalSection(&(device->mixlock));

    if (err != DS_OK)
        WARN("waveOutPause failed\n");

    return err;
}
Esempio n. 5
0
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
{
    HRESULT hres = DS_OK;
    TRACE("(%p, %d)\n", device, forcewave);

    waveOutClose(device->hwo);

    device->drvdesc.dwFlags = 0;

    hres = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode,
                             device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD_PTR)device,
                             CALLBACK_FUNCTION | WAVE_MAPPED));
    if (FAILED(hres)) {
        WARN("waveOutOpen failed: %08x\n", hres);
        return hres;
    }

    return hres;
}
Esempio n. 6
0
HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device)
{
	HRESULT err = DS_OK;
	TRACE("(%p)\n", device);

	if (device->hwbuf) {
		err = IDsDriverBuffer_Stop(device->hwbuf);
		if (err == DSERR_BUFFERLOST) {
			DSOUND_PrimaryClose(device);
			err = DSOUND_ReopenDevice(device, FALSE);
			if (FAILED(err))
				ERR("DSOUND_ReopenDevice failed\n");
			else
			{
				err = DSOUND_PrimaryOpen(device);
				if (FAILED(err))
					WARN("DSOUND_PrimaryOpen failed\n");
			}
		} else if (err != DS_OK) {
			WARN("IDsDriverBuffer_Stop failed\n");
		}
	} else {

		/* don't call the wave system with the lock set */
		LeaveCriticalSection(&(device->mixlock));
		/* **** */

		err = mmErr(waveOutPause(device->hwo));

		/* **** */
		EnterCriticalSection(&(device->mixlock));

		if (err != DS_OK)
			WARN("waveOutPause failed\n");
	}

	return err;
}
Esempio n. 7
0
HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave)
{
	HRESULT hres = DS_OK;
	TRACE("(%p, %d)\n", device, forcewave);

	if (device->driver)
	{
		IDsDriver_Close(device->driver);
		if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
			waveOutClose(device->hwo);
		IDsDriver_Release(device->driver);
		device->driver = NULL;
		device->buffer = NULL;
		device->hwo = 0;
	}
	else if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
		waveOutClose(device->hwo);

	/* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
	if (ds_hw_accel != DS_HW_ACCEL_EMULATION && !forcewave)
		waveOutMessage((HWAVEOUT)device->drvdesc.dnDevNode, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);

	/* Get driver description */
	if (device->driver) {
		DWORD wod = device->drvdesc.dnDevNode;
		hres = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
		device->drvdesc.dnDevNode = wod;
		if (FAILED(hres)) {
			WARN("IDsDriver_GetDriverDesc failed: %08x\n", hres);
			IDsDriver_Release(device->driver);
			device->driver = NULL;
		}
        }

        /* if no DirectSound interface available, use WINMM API instead */
	if (!device->driver)
		device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;

	if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
	{
		DWORD flags = CALLBACK_FUNCTION;

		if (device->driver)
			flags |= WAVE_DIRECTSOUND;

		hres = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode, device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD_PTR)device, flags));
		if (FAILED(hres)) {
			WARN("waveOutOpen failed\n");
			if (device->driver)
			{
				IDsDriver_Release(device->driver);
				device->driver = NULL;
			}
			return hres;
		}
	}

	if (device->driver)
		hres = IDsDriver_Open(device->driver);

	return hres;
}
Esempio n. 8
0
static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
{
	DWORD buflen;
	HRESULT err = DS_OK;
	TRACE("(%p)\n", device);

	/* on original windows, the buffer it set to a fixed size, no matter what the settings are.
	   on windows this size is always fixed (tested on win-xp) */
	if (!device->buflen)
		device->buflen = ds_hel_buflen;
	buflen = device->buflen;
	buflen -= buflen % device->pwfx->nBlockAlign;
	device->buflen = buflen;

	if (device->driver)
	{
		err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx,
						  DSBCAPS_PRIMARYBUFFER,0,
						  &(device->buflen),&(device->buffer),
						  (LPVOID*)&(device->hwbuf));

		if (err != DS_OK) {
			WARN("IDsDriver_CreateSoundBuffer failed (%08x), falling back to waveout\n", err);
			err = DSOUND_ReopenDevice(device, TRUE);
			if (FAILED(err))
			{
				WARN("Falling back to waveout failed too! Giving up\n");
				return err;
			}
		}
                if (device->hwbuf)
                    IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan);

                DSOUND_RecalcPrimary(device);
		device->prebuf = ds_snd_queue_max;
		if (device->helfrags < ds_snd_queue_min)
		{
			WARN("Too little sound buffer to be effective (%d/%d) falling back to waveout\n", device->buflen, ds_snd_queue_min * device->fraglen);
			device->buflen = buflen;
			IDsDriverBuffer_Release(device->hwbuf);
			device->hwbuf = NULL;
			err = DSOUND_ReopenDevice(device, TRUE);
			if (FAILED(err))
			{
				WARN("Falling back to waveout failed too! Giving up\n");
				return err;
			}
		}
		else if (device->helfrags < ds_snd_queue_max)
			device->prebuf = device->helfrags;
	}

	device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen);
	device->mix_buffer = HeapAlloc(GetProcessHeap(), 0, device->mix_buffer_len);
	if (!device->mix_buffer)
	{
		if (device->hwbuf)
			IDsDriverBuffer_Release(device->hwbuf);
		device->hwbuf = NULL;
		return DSERR_OUTOFMEMORY;
	}

	if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
	else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;

	/* are we using waveOut stuff? */
	if (!device->driver) {
		LPBYTE newbuf;
		LPWAVEHDR headers = NULL;
		DWORD overshot;
		unsigned int c;

		/* Start in pause mode, to allow buffers to get filled */
		waveOutPause(device->hwo);

		TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);

		/* reallocate emulated primary buffer */
		if (device->buffer)
			newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer, buflen);
		else
			newbuf = HeapAlloc(GetProcessHeap(),0, buflen);

		if (!newbuf) {
			ERR("failed to allocate primary buffer\n");
			return DSERR_OUTOFMEMORY;
			/* but the old buffer might still exist and must be re-prepared */
		}

		DSOUND_RecalcPrimary(device);
		if (device->pwave)
			headers = HeapReAlloc(GetProcessHeap(),0,device->pwave, device->helfrags * sizeof(WAVEHDR));
		else
			headers = HeapAlloc(GetProcessHeap(),0,device->helfrags * sizeof(WAVEHDR));

		if (!headers) {
			ERR("failed to allocate wave headers\n");
			HeapFree(GetProcessHeap(), 0, newbuf);
			DSOUND_RecalcPrimary(device);
			return DSERR_OUTOFMEMORY;
		}

		device->buffer = newbuf;
		device->pwave = headers;

		/* prepare fragment headers */
		for (c=0; c<device->helfrags; c++) {
			device->pwave[c].lpData = (char*)device->buffer + c*device->fraglen;
			device->pwave[c].dwBufferLength = device->fraglen;
			device->pwave[c].dwUser = (DWORD_PTR)device;
			device->pwave[c].dwFlags = 0;
			device->pwave[c].dwLoops = 0;
			err = mmErr(waveOutPrepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR)));
			if (err != DS_OK) {
				while (c--)
					waveOutUnprepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR));
				break;
			}
		}

		overshot = device->buflen % device->fraglen;
		/* sanity */
		if(overshot)
		{
			overshot -= overshot % device->pwfx->nBlockAlign;
			device->pwave[device->helfrags - 1].dwBufferLength += overshot;
		}

		TRACE("fraglen=%d, overshot=%d\n", device->fraglen, overshot);
	}
	device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1];
	device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
	FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
	FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
	device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0;
	return err;
}
Esempio n. 9
0
static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device)
{
    DWORD buflen;
    HRESULT err = DS_OK;
    LPBYTE newbuf;
    LPWAVEHDR headers = NULL;
    DWORD overshot;
    unsigned int c;

    TRACE("(%p)\n", device);

    /* on original windows, the buffer it set to a fixed size, no matter what the settings are.
       on windows this size is always fixed (tested on win-xp) */
    if (!device->buflen)
        device->buflen = ds_hel_buflen;
    buflen = device->buflen;
    buflen -= buflen % device->pwfx->nBlockAlign;
    device->buflen = buflen;

    device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen);
    device->mix_buffer = HeapAlloc(GetProcessHeap(), 0, device->mix_buffer_len);
    if (!device->mix_buffer)
        return DSERR_OUTOFMEMORY;

    if (device->state == STATE_PLAYING) device->state = STATE_STARTING;
    else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED;

    /* Start in pause mode, to allow buffers to get filled */
    waveOutPause(device->hwo);

    TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer);

    /* reallocate emulated primary buffer */
    if (device->buffer)
        newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer, buflen);
    else
        newbuf = HeapAlloc(GetProcessHeap(),0, buflen);

    if (!newbuf) {
        ERR("failed to allocate primary buffer\n");
        return DSERR_OUTOFMEMORY;
        /* but the old buffer might still exist and must be re-prepared */
    }

    DSOUND_RecalcPrimary(device);
    if (device->pwave)
        headers = HeapReAlloc(GetProcessHeap(),0,device->pwave, device->helfrags * sizeof(WAVEHDR));
    else
        headers = HeapAlloc(GetProcessHeap(),0,device->helfrags * sizeof(WAVEHDR));

    if (!headers) {
        ERR("failed to allocate wave headers\n");
        HeapFree(GetProcessHeap(), 0, newbuf);
        DSOUND_RecalcPrimary(device);
        return DSERR_OUTOFMEMORY;
    }

    device->buffer = newbuf;
    device->pwave = headers;

    /* prepare fragment headers */
    for (c=0; c<device->helfrags; c++) {
        device->pwave[c].lpData = (char*)device->buffer + c*device->fraglen;
        device->pwave[c].dwBufferLength = device->fraglen;
        device->pwave[c].dwUser = (DWORD_PTR)device;
        device->pwave[c].dwFlags = 0;
        device->pwave[c].dwLoops = 0;
        err = mmErr(waveOutPrepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR)));
        if (err != DS_OK) {
            while (c--)
                waveOutUnprepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR));
            break;
        }
    }

    overshot = device->buflen % device->fraglen;
    /* sanity */
    if(overshot)
    {
        overshot -= overshot % device->pwfx->nBlockAlign;
        device->pwave[device->helfrags - 1].dwBufferLength += overshot;
    }

    TRACE("fraglen=%d, overshot=%d\n", device->fraglen, overshot);

    device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1];
    device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1];
    FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0);
    FillMemory(device->mix_buffer, device->mix_buffer_len, 0);
    device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0;
    return err;
}