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 + -
显示快捷键?