⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 audio_05.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 4 页
字号:
    case WODM_UNPREPARE: 	return wodUnprepare	(wDevID, (LPWAVEHDR)dwParam1, 		dwParam2);    case WODM_GETDEVCAPS:	return wodGetDevCaps	(wDevID, (LPWAVEOUTCAPSA)dwParam1,	dwParam2);    case WODM_GETNUMDEVS:	return wodGetNumDevs	();    case WODM_GETPITCH:	 	return MMSYSERR_NOTSUPPORTED;    case WODM_SETPITCH:	 	return MMSYSERR_NOTSUPPORTED;    case WODM_GETPLAYBACKRATE:	return MMSYSERR_NOTSUPPORTED;    case WODM_SETPLAYBACKRATE:	return MMSYSERR_NOTSUPPORTED;    case WODM_GETVOLUME:	return wodGetVolume	(wDevID, (LPDWORD)dwParam1);    case WODM_SETVOLUME:	return wodSetVolume	(wDevID, dwParam1);    case WODM_RESTART:		return wodRestart	(wDevID);    case WODM_RESET:		return wodReset		(wDevID);    case DRV_QUERYDSOUNDIFACE:	return wodDsCreate(wDevID, (PIDSDRIVER*)dwParam1);    default:	FIXME("unknown message %d!\n", wMsg);    }    return MMSYSERR_NOTSUPPORTED;}/*======================================================================* *                  Low level DSOUND implementation			* *======================================================================*/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_UnmapPrimary(IDsDriverBufferImpl *dsdb){    WINE_WAVEOUT *wwo = &(WOutDev[dsdb->drv->wDevID]);    if (wwo->mmap_buffer) {	if (snd_pcm_munmap(wwo->handle, SND_PCM_CHANNEL_PLAYBACK) < 0) {	    ERR("(%p): Could not unmap sound device (errno=%d)\n", dsdb, errno);	    return DSERR_GENERIC;	}	wwo->mmap_buffer = wwo->mmap_control = 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); */    /* FIXME: we need to implement it */    TRACE("(%p)\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)\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 DSERR_UNSUPPORTED;}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){#if 0    ICOM_THIS(IDsDriverBufferImpl,iface);    TODO;    count_info info;    DWORD ptr;    TRACE("(%p)\n",iface);    if (WOutDev[This->drv->wDevID].handle == NULL) {	ERR("device not open, but accessing?\n");	return DSERR_UNINITIALIZED;    }    if (ioctl(WOutDev[This->drv->wDevID].unixdev, SNDCTL_DSP_GETOPTR, &info) < 0) {	ERR("ioctl failed (%d)\n", errno);	return DSERR_GENERIC;    }    ptr = info.ptr & ~3; /* align the pointer, just in case */    if (lpdwPlay) *lpdwPlay = ptr;    if (lpdwWrite) {	/* add some safety margin (not strictly necessary, but...) */	if (WOutDev[This->drv->wDevID].caps.dwSupport & WAVECAPS_SAMPLEACCURATE)	    *lpdwWrite = ptr + 32;	else	    *lpdwWrite = ptr + WOutDev[This->drv->wDevID].dwFragmentSize;	while (*lpdwWrite > This->buflen)	    *lpdwWrite -= This->buflen;    }#endif    TRACE("playpos=%ld, writepos=%ld\n", lpdwPlay?*lpdwPlay:0, lpdwWrite?*lpdwWrite:0);    return DS_OK;}static HRESULT WINAPI IDsDriverBufferImpl_Play(PIDSDRIVERBUFFER iface, DWORD dwRes1, DWORD dwRes2, DWORD dwFlags){    ICOM_THIS(IDsDriverBufferImpl,iface);    TRACE("(%p,%lx,%lx,%lx)\n",iface,dwRes1,dwRes2,dwFlags);    /* FIXME: error handling */    snd_pcm_playback_go(WOutDev[This->drv->wDevID].handle);    return DS_OK;}static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface){    ICOM_THIS(IDsDriverBufferImpl,iface);    TRACE("(%p)\n",iface);    /* no more playing */    /* FIXME: error handling */    snd_pcm_playback_drain(WOutDev[This->drv->wDevID].handle);    /* Most ALSA 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;    strcpy(pDesc->szDesc,"WineALSA DirectSound Driver");    strcpy(pDesc->szDrvName,"winealsa.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);    TRACE("(%p)\n",iface);    /* FIXME: error handling */    snd_pcm_channel_prepare(WOutDev[This->wDevID].handle, SND_PCM_CHANNEL_PLAYBACK);    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;    /* 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;    WINE_WAVEOUT *wwo = &(WOutDev[This->wDevID]);    struct snd_pcm_channel_setup setup;    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;    if (!wwo->mmap_buffer) {        if (snd_pcm_mmap(wwo->handle, SND_PCM_CHANNEL_PLAYBACK, &wwo->mmap_control, &wwo->mmap_buffer))        {	    ERR("(%p): Could not map sound device for direct access (%s)\n", *ippdsdb, snd_strerror(errno));	    return DSERR_GENERIC;	}	setup.mode = SND_PCM_MODE_BLOCK;	setup.channel = SND_PCM_CHANNEL_PLAYBACK;	if (snd_pcm_channel_setup(wwo->handle, &setup) < 0) {            ERR("Unable to obtain setup\n");            /* FIXME: resource cleanup */            return DSERR_GENERIC;	}        wwo->mmap_block_size = setup.buf.block.frag_size;        wwo->mmap_block_number = setup.buf.block.frags;	TRACE("(%p): sound device has been mapped for direct access at %p, size=%d\n",              *ippdsdb, wwo->mmap_buffer, setup.buf.block.frags * setup.buf.block.frag_size);#if 0	/* for some reason, es1371 and sblive! sometimes have junk in here.	 * clear it, or we get junk noise */	/* some libc implementations are buggy: their memset reads from the buffer...	 * to work around it, we have to zero the block by hand. We don't do the expected:	 * memset(wwo->mapping, 0, wwo->maplen);	 */	{	    char*	p1 = wwo->mapping;	    unsigned	len = wwo->maplen;	    if (len >= 16) /* so we can have at least a 4 long area to store... */	    {		/* the mmap:ed value is (at least) dword aligned		 * so, start filling the complete unsigned long:s		 */		int		b = len >> 2;		unsigned long*	p4 = (unsigned long*)p1;		while (b--) *p4++ = 0;		/* prepare for filling the rest */		len &= 3;		p1 = (unsigned char*)p4;	    }	    /* in all cases, fill the remaining bytes */	    while (len-- != 0) *p1++ = 0;	}#endif    }    /* primary buffer is ready to go */    *pdwcbBufferSize	= wwo->mmap_block_size * wwo->mmap_block_number;    *ppbBuffer		= wwo->mmap_buffer;    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;    (*idrv)->wDevID	= wDevID;    (*idrv)->primary	= NULL;    return MMSYSERR_NOERROR;}/* we don't need a default wodMessage for audio when we don't have ALSA, the * audio.c file will provide it for us */#endif /* HAVE_ALSA && interface == 0.5 */

⌨️ 快捷键说明

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