audio.c

来自「Wine-20031016」· C语言 代码 · 共 2,103 行 · 第 1/5 页

C
2,103
字号
 *		Elsewhere the driver returns Not Implemented for DIrectSound *		While it may be possible to map the sound device on Solaris *		Doing so would bypass the libaudioio library and therefore break any conversions *		that the libaudioio sample specification converter is doing *		**** All this is untested so far *======================================================================*/typedef struct IDsDriverImpl IDsDriverImpl;typedef struct IDsDriverBufferImpl IDsDriverBufferImpl;struct IDsDriverImpl{    /* IUnknown fields */    ICOM_VFIELD(IDsDriver);    DWORD		ref;    /* IDsDriverImpl fields */    UINT		wDevID;    IDsDriverBufferImpl*primary;};struct IDsDriverBufferImpl{    /* IUnknown fields */    ICOM_VFIELD(IDsDriverBuffer);    DWORD		ref;    /* IDsDriverBufferImpl fields */    IDsDriverImpl*	drv;    DWORD		buflen;};static HRESULT DSDB_MapPrimary(IDsDriverBufferImpl *dsdb){    WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]);    if (!wwo->mapping) {	wwo->mapping = mmap(NULL, wwo->maplen, PROT_WRITE, MAP_SHARED,			    wwo->unixdev, 0);	if (wwo->mapping == (LPBYTE)-1) {	    ERR("(%p): Could not map sound device for direct access (errno=%d)\n", dsdb, errno);	    return DSERR_GENERIC;	}	TRACE("(%p): sound device has been mapped for direct access at %p, size=%ld\n", dsdb, wwo->mapping, wwo->maplen);	/* for some reason, es1371 and sblive! sometimes have junk in here. */	memset(wwo->mapping,0,wwo->maplen); /* clear it, or we get junk noise */    }    return DS_OK;}static HRESULT DSDB_UnmapPrimary(IDsDriverBufferImpl *dsdb){    WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]);    if (wwo->mapping) {	if (munmap(wwo->mapping, wwo->maplen) < 0) {	    ERR("(%p): Could not unmap sound device (errno=%d)\n", dsdb, errno);	    return DSERR_GENERIC;	}	wwo->mapping = NULL;	TRACE("(%p): sound device unmapped\n", dsdb);    }    return DS_OK;}static HRESULT WINAPI IDsDriverBufferImpl_QueryInterface(PIDSDRIVERBUFFER iface, REFIID riid, LPVOID *ppobj){    /* ICOM_THIS(IDsDriverBufferImpl,iface); */    FIXME("(): stub!\n");    return DSERR_UNSUPPORTED;}static ULONG WINAPI IDsDriverBufferImpl_AddRef(PIDSDRIVERBUFFER iface){    ICOM_THIS(IDsDriverBufferImpl,iface);    This->ref++;    return This->ref;}static ULONG WINAPI IDsDriverBufferImpl_Release(PIDSDRIVERBUFFER iface){    ICOM_THIS(IDsDriverBufferImpl,iface);    if (--This->ref)	return This->ref;    if (This == This->drv->primary)	This->drv->primary = NULL;    DSDB_UnmapPrimary(This);    HeapFree(GetProcessHeap(),0,This);    return 0;}static HRESULT WINAPI IDsDriverBufferImpl_Lock(PIDSDRIVERBUFFER iface,					       LPVOID*ppvAudio1,LPDWORD pdwLen1,					       LPVOID*ppvAudio2,LPDWORD pdwLen2,					       DWORD dwWritePosition,DWORD dwWriteLen,					       DWORD dwFlags){    /* ICOM_THIS(IDsDriverBufferImpl,iface); */    /* since we (GetDriverDesc flags) have specified DSDDESC_DONTNEEDPRIMARYLOCK,     * and that we don't support secondary buffers, this method will never be called */    TRACE("(%p): stub\n",iface);    return DSERR_UNSUPPORTED;}static HRESULT WINAPI IDsDriverBufferImpl_Unlock(PIDSDRIVERBUFFER iface,						 LPVOID pvAudio1,DWORD dwLen1,						 LPVOID pvAudio2,DWORD dwLen2){    /* ICOM_THIS(IDsDriverBufferImpl,iface); */    TRACE("(%p): stub\n",iface);    return DSERR_UNSUPPORTED;}static HRESULT WINAPI IDsDriverBufferImpl_SetFormat(PIDSDRIVERBUFFER iface,						    LPWAVEFORMATEX pwfx){    /* ICOM_THIS(IDsDriverBufferImpl,iface); */    TRACE("(%p,%p)\n",iface,pwfx);    /* On our request (GetDriverDesc flags), DirectSound has by now used     * waveOutClose/waveOutOpen to set the format...     * unfortunately, this means our mmap() is now gone...     * so we need to somehow signal to our DirectSound implementation     * that it should completely recreate this HW buffer...     * this unexpected error code should do the trick... */    return DSERR_BUFFERLOST;}static HRESULT WINAPI IDsDriverBufferImpl_SetFrequency(PIDSDRIVERBUFFER iface, DWORD dwFreq){    /* ICOM_THIS(IDsDriverBufferImpl,iface); */    TRACE("(%p,%ld): stub\n",iface,dwFreq);    return DSERR_UNSUPPORTED;}static HRESULT WINAPI IDsDriverBufferImpl_SetVolumePan(PIDSDRIVERBUFFER iface, PDSVOLUMEPAN pVolPan){    /* ICOM_THIS(IDsDriverBufferImpl,iface); */    FIXME("(%p,%p): stub!\n",iface,pVolPan);    return DS_OK;}static HRESULT WINAPI IDsDriverBufferImpl_SetPosition(PIDSDRIVERBUFFER iface, DWORD dwNewPos){    /* ICOM_THIS(IDsDriverImpl,iface); */    TRACE("(%p,%ld): stub\n",iface,dwNewPos);    return DSERR_UNSUPPORTED;}static HRESULT WINAPI IDsDriverBufferImpl_GetPosition(PIDSDRIVERBUFFER iface,						      LPDWORD lpdwPlay, LPDWORD lpdwWrite){    ICOM_THIS(IDsDriverBufferImpl,iface);#if 0    count_info info;#endif    DWORD ptr;    TRACE("(%p)\n",iface);    if (WOutDev[This->drv->wDevID].unixdev == -1) {	ERR("device not open, but accessing?\n");	return DSERR_UNINITIALIZED;    }    /*Libaudioio doesn't support this (Yet anyway)*/     return DSERR_UNSUPPORTED;}static HRESULT WINAPI IDsDriverBufferImpl_Play(PIDSDRIVERBUFFER iface, DWORD dwRes1, DWORD dwRes2, DWORD dwFlags){    ICOM_THIS(IDsDriverBufferImpl,iface);#if 0    int enable = PCM_ENABLE_OUTPUT;    TRACE("(%p,%lx,%lx,%lx)\n",iface,dwRes1,dwRes2,dwFlags);    if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {	ERR("ioctl failed (%d)\n", errno);	return DSERR_GENERIC;    }#endif    return DS_OK;}static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface){    ICOM_THIS(IDsDriverBufferImpl,iface);    int enable = 0;#if 0    TRACE("(%p)\n",iface);    /* no more playing */    if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {	ERR("ioctl failed (%d)\n", errno);	return DSERR_GENERIC;    }#endif#if 0    /* the play position must be reset to the beginning of the buffer */    if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_RESET, 0) < 0) {	ERR("ioctl failed (%d)\n", errno);	return DSERR_GENERIC;    }#endif    /* Most OSS drivers just can't stop the playback without closing the device...     * so we need to somehow signal to our DirectSound implementation     * that it should completely recreate this HW buffer...     * this unexpected error code should do the trick... */    return DSERR_BUFFERLOST;}static ICOM_VTABLE(IDsDriverBuffer) dsdbvt ={    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE    IDsDriverBufferImpl_QueryInterface,    IDsDriverBufferImpl_AddRef,    IDsDriverBufferImpl_Release,    IDsDriverBufferImpl_Lock,    IDsDriverBufferImpl_Unlock,    IDsDriverBufferImpl_SetFormat,    IDsDriverBufferImpl_SetFrequency,    IDsDriverBufferImpl_SetVolumePan,    IDsDriverBufferImpl_SetPosition,    IDsDriverBufferImpl_GetPosition,    IDsDriverBufferImpl_Play,    IDsDriverBufferImpl_Stop};static HRESULT WINAPI IDsDriverImpl_QueryInterface(PIDSDRIVER iface, REFIID riid, LPVOID *ppobj){    /* ICOM_THIS(IDsDriverImpl,iface); */    FIXME("(%p): stub!\n",iface);    return DSERR_UNSUPPORTED;}static ULONG WINAPI IDsDriverImpl_AddRef(PIDSDRIVER iface){    ICOM_THIS(IDsDriverImpl,iface);    This->ref++;    return This->ref;}static ULONG WINAPI IDsDriverImpl_Release(PIDSDRIVER iface){    ICOM_THIS(IDsDriverImpl,iface);    if (--This->ref)	return This->ref;    HeapFree(GetProcessHeap(),0,This);    return 0;}static HRESULT WINAPI IDsDriverImpl_GetDriverDesc(PIDSDRIVER iface, PDSDRIVERDESC pDesc){    ICOM_THIS(IDsDriverImpl,iface);    TRACE("(%p,%p)\n",iface,pDesc);    pDesc->dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT |	DSDDESC_USESYSTEMMEMORY | DSDDESC_DONTNEEDPRIMARYLOCK;    strcpy(pDesc->szDesc,"Wine AudioIO DirectSound Driver");    strcpy(pDesc->szDrvName,"wineaudioio.drv");    pDesc->dnDevNode		= WOutDev[This->wDevID].waveDesc.dnDevNode;    pDesc->wVxdId		= 0;    pDesc->wReserved		= 0;    pDesc->ulDeviceNum		= This->wDevID;    pDesc->dwHeapType		= DSDHEAP_NOHEAP;    pDesc->pvDirectDrawHeap	= NULL;    pDesc->dwMemStartAddress	= 0;    pDesc->dwMemEndAddress	= 0;    pDesc->dwMemAllocExtra	= 0;    pDesc->pvReserved1		= NULL;    pDesc->pvReserved2		= NULL;    return DS_OK;}static HRESULT WINAPI IDsDriverImpl_Open(PIDSDRIVER iface){    ICOM_THIS(IDsDriverImpl,iface);    int enable = 0;    TRACE("(%p)\n",iface);    /* make sure the card doesn't start playing before we want it to */#if 0    if (ioctl(WOutDev[This->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {	ERR("ioctl failed (%d)\n", errno);	return DSERR_GENERIC;    }#endif    return DS_OK;}static HRESULT WINAPI IDsDriverImpl_Close(PIDSDRIVER iface){    ICOM_THIS(IDsDriverImpl,iface);    TRACE("(%p)\n",iface);    if (This->primary) {	ERR("problem with DirectSound: primary not released\n");	return DSERR_GENERIC;    }    return DS_OK;}static HRESULT WINAPI IDsDriverImpl_GetCaps(PIDSDRIVER iface, PDSDRIVERCAPS pCaps){    /* ICOM_THIS(IDsDriverImpl,iface); */    TRACE("(%p,%p)\n",iface,pCaps);    memset(pCaps, 0, sizeof(*pCaps));    /* FIXME: need to check actual capabilities */    pCaps->dwFlags = DSCAPS_PRIMARYMONO | DSCAPS_PRIMARYSTEREO |	DSCAPS_PRIMARY8BIT | DSCAPS_PRIMARY16BIT;    pCaps->dwPrimaryBuffers = 1;    pCaps->dwMinSecondarySampleRate = DSBFREQUENCY_MIN;    pCaps->dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;    /* the other fields only apply to secondary buffers, which we don't support     * (unless we want to mess with wavetable synthesizers and MIDI) */    return DS_OK;}static HRESULT WINAPI IDsDriverImpl_CreateSoundBuffer(PIDSDRIVER iface,						      LPWAVEFORMATEX pwfx,						      DWORD dwFlags, DWORD dwCardAddress,						      LPDWORD pdwcbBufferSize,						      LPBYTE *ppbBuffer,						      LPVOID *ppvObj){    ICOM_THIS(IDsDriverImpl,iface);    IDsDriverBufferImpl** ippdsdb = (IDsDriverBufferImpl**)ppvObj;    HRESULT err;#if 0    audio_buf_info info;#endif    int enable = 0;    TRACE("(%p,%p,%lx,%lx)\n",iface,pwfx,dwFlags,dwCardAddress);    /* we only support primary buffers */    if (!(dwFlags & DSBCAPS_PRIMARYBUFFER))	return DSERR_UNSUPPORTED;    if (This->primary)	return DSERR_ALLOCATED;    if (dwFlags & (DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN))	return DSERR_CONTROLUNAVAIL;    *ippdsdb = (IDsDriverBufferImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDsDriverBufferImpl));    if (*ippdsdb == NULL)	return DSERR_OUTOFMEMORY;    (*ippdsdb)->lpVtbl  = &dsdbvt;    (*ippdsdb)->ref	= 1;    (*ippdsdb)->drv	= This;    /* check how big the DMA buffer is now */#if 0    if (ioctl(WOutDev[This->wDevID].unixdev, SNDCTL_DSP_GETOSPACE, &info) < 0) {	ERR("ioctl failed (%d)\n", errno);	HeapFree(GetProcessHeap(),0,*ippdsdb);	*ippdsdb = NULL;	return DSERR_GENERIC;    }#endif    WOutDev[This->wDevID].maplen =64*1024; /* Map 64 K at a time */#if 0    (*ippdsdb)->buflen = info.fragstotal * info.fragsize;#endif    /* map the DMA buffer */    err = DSDB_MapPrimary(*ippdsdb);    if (err != DS_OK) {	HeapFree(GetProcessHeap(),0,*ippdsdb);	*ippdsdb = NULL;	return err;    }    /* primary buffer is ready to go */    *pdwcbBufferSize	= WOutDev[This->wDevID].maplen;    *ppbBuffer		= WOutDev[This->wDevID].mapping;    /* some drivers need some extra nudging after mapping */#if 0    if (ioctl(WOutDev[This->wDevID].unixdev, SNDCTL_DSP_SETTRIGGER, &enable) < 0) {	ERR("ioctl failed (%d)\n", errno);	return DSERR_GENERIC;    }#endif    This->primary = *ippdsdb;    return DS_OK;}static HRESULT WINAPI IDsDriverImpl_DuplicateSoundBuffer(PIDSDRIVER iface,							 PIDSDRIVERBUFFER pBuffer,							 LPVOID *ppvObj){    /* ICOM_THIS(IDsDriverImpl,iface); */    TRACE("(%p,%p): stub\n",iface,pBuffer);    return DSERR_INVALIDCALL;}static ICOM_VTABLE(IDsDriver) dsdvt ={    ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE    IDsDriverImpl_QueryInterface,    IDsDriverImpl_AddRef,    IDsDriverImpl_Release,    IDsDriverImpl_GetDriverDesc,    IDsDriverImpl_Open,    IDsDriverImpl_Close,    IDsDriverImpl_GetCaps,    IDsDriverImpl_CreateSoundBuffer,    IDsDriverImpl_DuplicateSoundBuffer};static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv){    IDsDriverImpl** idrv = (IDsDriverImpl**)drv;    /* the HAL isn't much better than the HEL if we can't do mmap() */    if (!(WOutDev[wDevID].caps.dwSupport & WAVECAPS_DIRECTSOUND)) {	ERR("DirectSound flag not set\n");	MESSAGE("This sound card's driver does not support direct access\n");	MESSAGE("The (slower) DirectSound HEL mode will be used instead.\n");	return MMSYSERR_NOTSUPPORTED;    }    *idrv = (IDsDriverImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDsDriverImpl));    if (!*idrv)	return MMSYSERR_NOMEM;    (*idrv)->lpVtbl	= &dsdvt;    (*idrv)->ref	= 1;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?