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

📄 audio.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 5 页
字号:
    EXIT_ON_ERROR( snd_pcm_sw_params_set_avail_min(pcm, sw_params, period_size), MMSYSERR_ERROR, "unable to set avail min");    EXIT_ON_ERROR( snd_pcm_sw_params_set_xfer_align(pcm, sw_params, 1), MMSYSERR_ERROR, "unable to set xfer align");    EXIT_ON_ERROR( snd_pcm_sw_params_set_silence_threshold(pcm, sw_params, 0), MMSYSERR_ERROR, "unable to set silence threshold");    EXIT_ON_ERROR( snd_pcm_sw_params(pcm, sw_params), MMSYSERR_ERROR, "unable to set sw params for playback");#undef EXIT_ON_ERROR    snd_pcm_prepare(pcm);    if (TRACE_ON(wave))	ALSA_TraceParameters(hw_params, sw_params, FALSE);    /* now, we can save all required data for later use... */    if ( wwo->hw_params )    	snd_pcm_hw_params_free(wwo->hw_params);    snd_pcm_hw_params_malloc(&(wwo->hw_params));    snd_pcm_hw_params_copy(wwo->hw_params, hw_params);    wwo->dwBufferSize = buffer_size;    wwo->lpQueuePtr = wwo->lpPlayPtr = wwo->lpLoopPtr = NULL;    wwo->p_handle = pcm;    ALSA_InitRingMessage(&wwo->msgRing);    wwo->count = snd_pcm_poll_descriptors_count (wwo->p_handle);    if (wwo->count <= 0) {	ERR("Invalid poll descriptors count\n");	return MMSYSERR_ERROR;    }    wwo->ufds = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(struct pollfd) * wwo->count);    if (wwo->ufds == NULL) {	ERR("No enough memory\n");	return MMSYSERR_NOMEM;    }    if ((err = snd_pcm_poll_descriptors(wwo->p_handle, wwo->ufds, wwo->count)) < 0) {	ERR("Unable to obtain poll descriptors for playback: %s\n", snd_strerror(err));	return MMSYSERR_ERROR;    }    if (!(dwFlags & WAVE_DIRECTSOUND)) {	wwo->hStartUpEvent = CreateEventA(NULL, FALSE, FALSE, NULL);	wwo->hThread = CreateThread(NULL, 0, wodPlayer, (LPVOID)(DWORD)wDevID, 0, &(wwo->dwThreadID));	WaitForSingleObject(wwo->hStartUpEvent, INFINITE);	CloseHandle(wwo->hStartUpEvent);    } else {	wwo->hThread = INVALID_HANDLE_VALUE;	wwo->dwThreadID = 0;    }    wwo->hStartUpEvent = INVALID_HANDLE_VALUE;    TRACE("handle=%08lx \n", (DWORD)wwo->p_handle);/*    if (wwo->dwFragmentSize % wwo->format.wf.nBlockAlign)	ERR("Fragment doesn't contain an integral number of data blocks\n");*/    TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%lu, nSamplesPerSec=%lu, nChannels=%u nBlockAlign=%u!\n",	  wwo->format.wBitsPerSample, wwo->format.wf.nAvgBytesPerSec,	  wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,	  wwo->format.wf.nBlockAlign);    return wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);}/************************************************************************** * 				wodClose			[internal] */static DWORD wodClose(WORD wDevID){    DWORD		ret = MMSYSERR_NOERROR;    WINE_WAVEOUT*	wwo;    TRACE("(%u);\n", wDevID);    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].p_handle == NULL) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    wwo = &WOutDev[wDevID];    if (wwo->lpQueuePtr) {	WARN("buffers still playing !\n");	ret = WAVERR_STILLPLAYING;    } else {	if (wwo->hThread != INVALID_HANDLE_VALUE) {	    ALSA_AddRingMessage(&wwo->msgRing, WINE_WM_CLOSING, 0, TRUE);	}        ALSA_DestroyRingMessage(&wwo->msgRing);	snd_pcm_hw_params_free(wwo->hw_params);	wwo->hw_params = NULL;        snd_pcm_close(wwo->p_handle);	wwo->p_handle = NULL;	ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);    }    HeapFree(GetProcessHeap(), 0, wwo->ufds);    return ret;}/************************************************************************** * 				wodWrite			[internal] * */static DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize){    TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);    /* first, do the sanity checks... */    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].p_handle == NULL) {        WARN("bad dev ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))	return WAVERR_UNPREPARED;    if (lpWaveHdr->dwFlags & WHDR_INQUEUE)	return WAVERR_STILLPLAYING;    lpWaveHdr->dwFlags &= ~WHDR_DONE;    lpWaveHdr->dwFlags |= WHDR_INQUEUE;    lpWaveHdr->lpNext = 0;    ALSA_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_HEADER, (DWORD)lpWaveHdr, FALSE);    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodPrepare			[internal] */static DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize){    TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);    if (wDevID >= MAX_WAVEOUTDRV) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (lpWaveHdr->dwFlags & WHDR_INQUEUE)	return WAVERR_STILLPLAYING;    lpWaveHdr->dwFlags |= WHDR_PREPARED;    lpWaveHdr->dwFlags &= ~WHDR_DONE;    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodUnprepare			[internal] */static DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize){    TRACE("(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);    if (wDevID >= MAX_WAVEOUTDRV) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (lpWaveHdr->dwFlags & WHDR_INQUEUE)	return WAVERR_STILLPLAYING;    lpWaveHdr->dwFlags &= ~WHDR_PREPARED;    lpWaveHdr->dwFlags |= WHDR_DONE;    return MMSYSERR_NOERROR;}/************************************************************************** * 			wodPause				[internal] */static DWORD wodPause(WORD wDevID){    TRACE("(%u);!\n", wDevID);    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].p_handle == NULL) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    ALSA_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_PAUSING, 0, TRUE);    return MMSYSERR_NOERROR;}/************************************************************************** * 			wodRestart				[internal] */static DWORD wodRestart(WORD wDevID){    TRACE("(%u);\n", wDevID);    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].p_handle == NULL) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (WOutDev[wDevID].state == WINE_WS_PAUSED) {	ALSA_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_RESTARTING, 0, TRUE);    }    /* FIXME: is NotifyClient with WOM_DONE right ? (Comet Busters 1.3.3 needs this notification) */    /* FIXME: Myst crashes with this ... hmm -MM       return wodNotifyClient(wwo, WOM_DONE, 0L, 0L);    */    return MMSYSERR_NOERROR;}/************************************************************************** * 			wodReset				[internal] */static DWORD wodReset(WORD wDevID){    TRACE("(%u);\n", wDevID);    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].p_handle == NULL) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    ALSA_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_RESETTING, 0, TRUE);    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodGetPosition			[internal] */static DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize){    int			time;    DWORD		val;    WINE_WAVEOUT*	wwo;    TRACE("(%u, %p, %lu);\n", wDevID, lpTime, uSize);    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].p_handle == NULL) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (lpTime == NULL)	return MMSYSERR_INVALPARAM;    wwo = &WOutDev[wDevID];    ALSA_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);    val = wwo->dwPlayedTotal;    TRACE("wType=%04X wBitsPerSample=%u nSamplesPerSec=%lu nChannels=%u nAvgBytesPerSec=%lu\n",	  lpTime->wType, wwo->format.wBitsPerSample,	  wwo->format.wf.nSamplesPerSec, wwo->format.wf.nChannels,	  wwo->format.wf.nAvgBytesPerSec);    TRACE("dwPlayedTotal=%lu\n", val);    switch (lpTime->wType) {    case TIME_BYTES:	lpTime->u.cb = val;	TRACE("TIME_BYTES=%lu\n", lpTime->u.cb);	break;    case TIME_SAMPLES:	lpTime->u.sample = val * 8 / wwo->format.wBitsPerSample /wwo->format.wf.nChannels;	TRACE("TIME_SAMPLES=%lu\n", lpTime->u.sample);	break;    case TIME_SMPTE:	time = val / (wwo->format.wf.nAvgBytesPerSec / 1000);	lpTime->u.smpte.hour = time / 108000;	time -= lpTime->u.smpte.hour * 108000;	lpTime->u.smpte.min = time / 1800;	time -= lpTime->u.smpte.min * 1800;	lpTime->u.smpte.sec = time / 30;	time -= lpTime->u.smpte.sec * 30;	lpTime->u.smpte.frame = time;	lpTime->u.smpte.fps = 30;	TRACE("TIME_SMPTE=%02u:%02u:%02u:%02u\n",	      lpTime->u.smpte.hour, lpTime->u.smpte.min,	      lpTime->u.smpte.sec, lpTime->u.smpte.frame);	break;    default:	FIXME("Format %d not supported ! use TIME_MS !\n", lpTime->wType);	lpTime->wType = TIME_MS;    case TIME_MS:	lpTime->u.ms = val / (wwo->format.wf.nAvgBytesPerSec / 1000);	TRACE("TIME_MS=%lu\n", lpTime->u.ms);	break;    }    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodBreakLoop			[internal] */static DWORD wodBreakLoop(WORD wDevID){    TRACE("(%u);\n", wDevID);    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].p_handle == NULL) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    ALSA_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_BREAKLOOP, 0, TRUE);    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodGetVolume			[internal] */static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol){    WORD	       left, right;    WINE_WAVEOUT*      wwo;    int                count;    long               min, max;    TRACE("(%u, %p);\n", wDevID, lpdwVol);    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].p_handle == NULL) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    wwo = &WOutDev[wDevID];    count = snd_ctl_elem_info_get_count(wwo->playback_einfo);    min = snd_ctl_elem_info_get_min(wwo->playback_einfo);    max = snd_ctl_elem_info_get_max(wwo->playback_einfo);#define VOLUME_ALSA_TO_WIN(x) (((x)-min) * 65536 /(max-min))    if (lpdwVol == NULL)	return MMSYSERR_NOTENABLED;    switch (count)    {   	case 2:	    left = VOLUME_ALSA_TO_WIN(snd_ctl_elem_value_get_integer(wwo->playback_evalue, 0));	    right = VOLUME_ALSA_TO_WIN(snd_ctl_elem_value_get_integer(wwo->playback_evalue, 1));	    break;	case 1:	    left = right = VOLUME_ALSA_TO_WIN(snd_ctl_elem_value_get_integer(wwo->playback_evalue, 0));	    break;	default:	    WARN("%d channels mixer not supported\n", count);	    return MMSYSERR_NOERROR;     }#undef VOLUME_ALSA_TO_WIN    TRACE("left=%d right=%d !\n", left, right);    *lpdwVol = MAKELONG( left, right );    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodSetVolume			[internal] */static DWORD wodSetVolume(WORD wDevID, DWORD dwParam){    WORD	       left, right;    WINE_WAVEOUT*      wwo;    int                count, err;    long               min, max;    TRACE("(%u, %08lX);\n", wDevID, dwParam);    if (wDevID >= MAX_WAVEOUTDRV || WOutDev[wDevID].p_handle == NULL) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    wwo = &WOutDev[wDevID];    count=snd_ctl_elem_info_get_count(wwo->playback_einfo);    min = snd_ctl_elem_info_get_min(wwo->playback_einfo);    max = snd_ctl_elem_info_get_max(wwo->playback_einfo);    left  = LOWORD(dwParam);    right = HIWORD(dwParam);#define VOLUME_WIN_TO_ALSA(x) ( (((x) * (max-min)) / 65536) + min )    switch (count)    {   	case 2:	    snd_ctl_elem_value_set_integer(wwo->playback_evalue, 0, VOLUME_WIN_TO_ALSA(left));	    snd_ctl_elem_value_set_integer(wwo->playback_evalue, 1, VOLUME_WIN_TO_ALSA(right));	    break;	case 1:	    snd_ctl_elem_value_set_integer(wwo->playback_evalue, 0, VOLUME_WIN_TO_ALSA(left));	    break;	default:	    WARN("%d channels mixer not supported\n", count);     }#undef VOLUME_WIN_TO_ALSA    if ( (err = snd_ctl_elem_write(wwo->ctl, wwo->playback_evalue)) < 0)    {	ERR("error writing snd_ctl_elem_value: %s\n", snd_strerror(err));    }    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodGetNumDevs			[internal] */

⌨️ 快捷键说明

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