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

📄 audio.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 5 页
字号:
static	DWORD	wodGetNumDevs(void){    return ALSA_WodNumDevs;}/************************************************************************** * 				wodMessage (WINEALSA.@) */DWORD WINAPI ALSA_wodMessage(UINT wDevID, UINT wMsg, DWORD dwUser,                             DWORD dwParam1, DWORD dwParam2){    TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",	  wDevID, wMsg, dwUser, dwParam1, dwParam2);    switch (wMsg) {    case DRVM_INIT:    case DRVM_EXIT:    case DRVM_ENABLE:    case DRVM_DISABLE:	/* FIXME: Pretend this is supported */	return 0;    case WODM_OPEN:	 	return wodOpen		(wDevID, (LPWAVEOPENDESC)dwParam1,	dwParam2);    case WODM_CLOSE:	 	return wodClose		(wDevID);    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_WRITE:	 	return wodWrite		(wDevID, (LPWAVEHDR)dwParam1,		dwParam2);    case WODM_PAUSE:	 	return wodPause		(wDevID);    case WODM_GETPOS:	 	return wodGetPosition	(wDevID, (LPMMTIME)dwParam1, 		dwParam2);    case WODM_BREAKLOOP: 	return wodBreakLoop     (wDevID);    case WODM_PREPARE:	 	return wodPrepare	(wDevID, (LPWAVEHDR)dwParam1, 		dwParam2);    case WODM_UNPREPARE: 	return wodUnprepare	(wDevID, (LPWAVEHDR)dwParam1, 		dwParam2);    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);    case DRV_QUERYDSOUNDDESC:	return wodDsDesc	(wDevID, (PDSDRIVERDESC)dwParam1);    case DRV_QUERYDSOUNDGUID:	return wodDsGuid	(wDevID, (LPGUID)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;    CRITICAL_SECTION          mmap_crst;    LPVOID                    mmap_buffer;    DWORD                     mmap_buflen_bytes;    snd_pcm_uframes_t         mmap_buflen_frames;    snd_pcm_channel_area_t *  mmap_areas;    snd_async_handler_t *     mmap_async_handler;};static void DSDB_CheckXRUN(IDsDriverBufferImpl* pdbi){    WINE_WAVEOUT *     wwo = &(WOutDev[pdbi->drv->wDevID]);    snd_pcm_state_t    state = snd_pcm_state(wwo->p_handle);    if ( state == SND_PCM_STATE_XRUN )    {	int            err = snd_pcm_prepare(wwo->p_handle);	TRACE("xrun occurred\n");	if ( err < 0 )            ERR("recovery from xrun failed, prepare failed: %s\n", snd_strerror(err));    }    else if ( state == SND_PCM_STATE_SUSPENDED )    {	int            err = snd_pcm_resume(wwo->p_handle);	TRACE("recovery from suspension occurred\n");        if (err < 0 && err != -EAGAIN){            err = snd_pcm_prepare(wwo->p_handle);            if (err < 0)                ERR("recovery from suspend failed, prepare failed: %s\n", snd_strerror(err));        }    }}static void DSDB_MMAPCopy(IDsDriverBufferImpl* pdbi){    WINE_WAVEOUT *     wwo = &(WOutDev[pdbi->drv->wDevID]);    int                channels;    snd_pcm_format_t   format;    snd_pcm_uframes_t  period_size;    snd_pcm_sframes_t  avail;    if ( !pdbi->mmap_buffer || !wwo->hw_params || !wwo->p_handle)    	return;    channels = snd_pcm_hw_params_get_channels(wwo->hw_params);    format = snd_pcm_hw_params_get_format(wwo->hw_params);    period_size = snd_pcm_hw_params_get_period_size(wwo->hw_params, 0);    avail = snd_pcm_avail_update(wwo->p_handle);    DSDB_CheckXRUN(pdbi);    TRACE("avail=%d format=%s channels=%d\n", (int)avail, snd_pcm_format_name(format), channels );    while (avail >= period_size)    {	const snd_pcm_channel_area_t *areas;	snd_pcm_uframes_t     ofs;	snd_pcm_uframes_t     frames;	int                   err;	frames = avail / period_size * period_size; /* round down to a multiple of period_size */	EnterCriticalSection(&pdbi->mmap_crst);	snd_pcm_mmap_begin(wwo->p_handle, &areas, &ofs, &frames);	snd_pcm_areas_copy(areas, ofs, pdbi->mmap_areas, ofs, channels, frames, format);	err = snd_pcm_mmap_commit(wwo->p_handle, ofs, frames);	LeaveCriticalSection(&pdbi->mmap_crst);	if ( err != (snd_pcm_sframes_t) frames)	    ERR("mmap partially failed.\n");	avail = snd_pcm_avail_update(wwo->p_handle);    } }static void DSDB_PCMCallback(snd_async_handler_t *ahandler){    /* snd_pcm_t *               handle = snd_async_handler_get_pcm(ahandler); */    IDsDriverBufferImpl*      pdbi = snd_async_handler_get_callback_private(ahandler);    TRACE("callback called\n");    DSDB_MMAPCopy(pdbi);}static int DSDB_CreateMMAP(IDsDriverBufferImpl* pdbi) {    WINE_WAVEOUT *            wwo = &(WOutDev[pdbi->drv->wDevID]);    snd_pcm_format_t          format = snd_pcm_hw_params_get_format(wwo->hw_params);    snd_pcm_uframes_t         frames = snd_pcm_hw_params_get_buffer_size(wwo->hw_params);    int                       channels = snd_pcm_hw_params_get_channels(wwo->hw_params);    unsigned int              bits_per_sample = snd_pcm_format_physical_width(format);    unsigned int              bits_per_frame = bits_per_sample * channels;    snd_pcm_channel_area_t *  a;    unsigned int              c;    int                       err;    if (TRACE_ON(wave))	ALSA_TraceParameters(wwo->hw_params, NULL, FALSE);    TRACE("format=%s  frames=%ld  channels=%d  bits_per_sample=%d  bits_per_frame=%d\n",          snd_pcm_format_name(format), frames, channels, bits_per_sample, bits_per_frame);    pdbi->mmap_buflen_frames = frames;    pdbi->mmap_buflen_bytes = snd_pcm_frames_to_bytes( wwo->p_handle, frames );    pdbi->mmap_buffer = HeapAlloc(GetProcessHeap(),0,pdbi->mmap_buflen_bytes);    if (!pdbi->mmap_buffer)	return DSERR_OUTOFMEMORY;    snd_pcm_format_set_silence(format, pdbi->mmap_buffer, frames );    TRACE("created mmap buffer of %ld frames (%ld bytes) at %p\n",        frames, pdbi->mmap_buflen_bytes, pdbi->mmap_buffer);    pdbi->mmap_areas = HeapAlloc(GetProcessHeap(),0,channels*sizeof(snd_pcm_channel_area_t));    if (!pdbi->mmap_areas)	return DSERR_OUTOFMEMORY;    a = pdbi->mmap_areas;    for (c = 0; c < channels; c++, a++)    {	a->addr = pdbi->mmap_buffer;	a->first = bits_per_sample * c;	a->step = bits_per_frame;	TRACE("Area %d: addr=%p  first=%d  step=%d\n", c, a->addr, a->first, a->step);    }    InitializeCriticalSection(&pdbi->mmap_crst);    err = snd_async_add_pcm_handler(&pdbi->mmap_async_handler, wwo->p_handle, DSDB_PCMCallback, pdbi);    if ( err < 0 )     { 	ERR("add_pcm_handler failed. reason: %s\n", snd_strerror(err));	return DSERR_GENERIC;     }    return DS_OK; }static void DSDB_DestroyMMAP(IDsDriverBufferImpl* pdbi){    TRACE("mmap buffer %p destroyed\n", pdbi->mmap_buffer);    HeapFree(GetProcessHeap(), 0, pdbi->mmap_areas);    HeapFree(GetProcessHeap(), 0, pdbi->mmap_buffer);    pdbi->mmap_areas = NULL;    pdbi->mmap_buffer = NULL;    DeleteCriticalSection(&pdbi->mmap_crst);}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);    TRACE("(%p)\n",iface);    return ++This->ref;}static ULONG WINAPI IDsDriverBufferImpl_Release(PIDSDRIVERBUFFER iface){    ICOM_THIS(IDsDriverBufferImpl,iface);    TRACE("(%p)\n",iface);    if (--This->ref)	return This->ref;    if (This == This->drv->primary)	This->drv->primary = NULL;    DSDB_DestroyMMAP(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); */    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);    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);    WINE_WAVEOUT *      wwo = &(WOutDev[This->drv->wDevID]);    snd_pcm_uframes_t   hw_ptr;    snd_pcm_uframes_t   period_size;    if (wwo->hw_params == NULL) return DSERR_GENERIC;    period_size  = snd_pcm_hw_params_get_period_size(wwo->hw_params, 0);    if (wwo->p_handle == NULL) return DSERR_GENERIC;    /** we need to track down buffer underruns */    DSDB_CheckXRUN(This);    EnterCriticalSection(&This->mmap_crst);    hw_ptr = _snd_pcm_mmap_hw_ptr(wwo->p_handle);    if (lpdwPlay)	*lpdwPlay = snd_pcm_frames_to_bytes(wwo->p_handle, hw_ptr/ period_size  * period_size) % This->mmap_buflen_bytes;    if (lpdwWrite)	*lpdwWrite = snd_pcm_frames_to_bytes(wwo->p_handle, (hw_ptr / period_size + 1) * period_size ) % This->mmap_buflen_bytes;    LeaveCriticalSection(&This->mmap_crst);    TRACE("hw_ptr=0x%08x, playpos=%ld, writepos=%ld\n", (unsigned int)hw_ptr, lpdwPlay?*lpdwPlay:-1, lpdwWrite?*lpdwWrite:-1);    return DS_OK;}static HRESULT WINAPI IDsDriverBufferImpl_Play(PIDSDRIVERBUFFER iface, DWORD dwRes1, DWORD dwRes2, DWORD dwFlags){    ICOM_THIS(IDsDriverBufferImpl,iface);    WINE_WAVEOUT *       wwo = &(WOutDev[This->drv->wDevID]);    snd_pcm_state_t      state;    int                  err;    TRACE("(%p,%lx,%lx,%lx)\n",iface,dwRes1,dwRes2,dwFlags);    if (wwo->p_handle == NULL) return DSERR_GENERIC;    state = snd_pcm_state(wwo->p_handle);    if ( state == SND_PCM_STATE_SETUP )    {	err = snd_pcm_prepare(wwo->p_handle);        state = snd_pcm_state(wwo->p_handle);    }    if ( state == SND_PCM_STATE_PREPARED )     {	DSDB_MMAPCopy(This);	err = snd_pcm_start(wwo->p_handle);     }    return DS_OK;}static HRESULT WINAPI IDsDriverBufferImpl_Stop(PIDSDRIVERBUFFER iface){    ICOM_THIS(IDsDriverBufferImpl,iface);    WINE_WAVEOUT *    wwo = &(WOutDev[This->drv->wDevID]);    int               err;    DWORD             play;    DWORD             write;    TRACE("(%p)\n",iface);    if (wwo->p_handle == NULL) return DSERR_GENERIC;    /* ring buffer wrap up detection */    IDsDriverBufferImpl_GetPosition(iface, &play, &write);    if ( play > write)    {	TRACE("writepos wrapper up\n");    	return DS_OK;    }    if ( ( err = snd_pcm_drop(wwo->p_handle)) < 0 )    {   	ERR("error while stopping pcm: %s\n", snd_strerror(err));	return DSERR_GENERIC;    }    return DS_OK;}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,    IDsDriverBuffer

⌨️ 快捷键说明

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