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

📄 audio_05.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 4 页
字号:
	return MMSYSERR_NOERROR;    }    wwo = &WOutDev[wDevID];    if ((dwFlags & WAVE_DIRECTSOUND) && !(wwo->caps.dwSupport & WAVECAPS_DIRECTSOUND))	/* not supported, ignore it */	dwFlags &= ~WAVE_DIRECTSOUND;    wwo->handle = 0;    if (snd_pcm_open(&wwo->handle, wDevID, 0, SND_PCM_OPEN_DUPLEX|SND_PCM_OPEN_NONBLOCK))    {        ERR("Error open: %s\n", snd_strerror(errno));	return MMSYSERR_NOTENABLED;    }    memset(&params, 0, sizeof(params));    params.channel = SND_PCM_CHANNEL_PLAYBACK;    params.start_mode = SND_PCM_START_DATA;    params.stop_mode = SND_PCM_STOP_STOP;    params.mode = SND_PCM_MODE_STREAM;    params.buf.stream.queue_size = 0x1000;    params.buf.stream.fill = SND_PCM_FILL_SILENCE;    params.buf.stream.max_fill = 0x800;    wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);    memcpy(&wwo->waveDesc, lpDesc, 	     sizeof(WAVEOPENDESC));    memcpy(&wwo->format,   lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));    if (wwo->format.wBitsPerSample == 0) {	WARN("Resetting zeroed wBitsPerSample\n");	wwo->format.wBitsPerSample = 8 *	    (wwo->format.wf.nAvgBytesPerSec /	     wwo->format.wf.nSamplesPerSec) /	    wwo->format.wf.nChannels;    }    params.format.interleave = 1;    params.format.format = (wwo->format.wBitsPerSample == 16) ?        SND_PCM_SFMT_S16_LE : SND_PCM_SFMT_U8;    params.format.rate = wwo->format.wf.nSamplesPerSec;    params.format.voices = (wwo->format.wf.nChannels > 1) ? 2 : 1;    params.format.special = 0;    if (snd_pcm_channel_params(wwo->handle, &params))    {        ERR("Can't set params: %s\n", snd_strerror(errno));        snd_pcm_close(wwo->handle);        wwo->handle = NULL;        return MMSYSERR_INVALPARAM;    }#if 0    TODO;    if (params.format.rate != format != ((wwo->format.wBitsPerSample == 16) ? AFMT_S16_LE : AFMT_U8))	ERR("Can't set format to %d (%d)\n",	    (wwo->format.wBitsPerSample == 16) ? AFMT_S16_LE : AFMT_U8, format);    if (dsp_stereo != (wwo->format.wf.nChannels > 1) ? 1 : 0)	ERR("Can't set stereo to %u (%d)\n",	    (wwo->format.wf.nChannels > 1) ? 1 : 0, dsp_stereo);    if (!NEAR_MATCH(sample_rate, wwo->format.wf.nSamplesPerSec))	ERR("Can't set sample_rate to %lu (%d)\n",	    wwo->format.wf.nSamplesPerSec, sample_rate);#endif    snd_pcm_playback_prepare(wwo->handle);    /* Remember fragsize and total buffer size for future use */    wwo->dwBufferSize = params.buf.stream.queue_size;    /* FIXME: should get rid off fragment size */    wwo->dwFragmentSize = wwo->dwBufferSize >> 4; /* why not */    wwo->dwPlayedTotal = 0;    wwo->dwWrittenTotal = 0;    wwo->lpQueuePtr = wwo->lpPlayPtr = wwo->lpLoopPtr = NULL;    ALSA_InitRingMessage(&wwo->msgRing);    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 fragmentSize=%ld\n",	  (DWORD)wwo->handle, wwo->dwFragmentSize);    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].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);	}	if (wwo->mmap_buffer) {            snd_pcm_munmap(wwo->handle, SND_PCM_CHANNEL_PLAYBACK);            wwo->mmap_buffer = wwo->mmap_control = NULL;	}        ALSA_DestroyRingMessage(&wwo->msgRing);        snd_pcm_close(wwo->handle);	wwo->handle = NULL;	wwo->dwFragmentSize = 0;	ret = wodNotifyClient(wwo, WOM_CLOSE, 0L, 0L);    }    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].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].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].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].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].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].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){#if 0    int 	mixer;#endif    int		volume;    DWORD	left, right;    TRACE("(%u, %p);\n", wDevID, lpdwVol);    if (lpdwVol == NULL)	return MMSYSERR_NOTENABLED;#if 0    TODO;    if ((mixer = open(MIXER_DEV, O_RDONLY|O_NDELAY)) < 0) {	WARN("mixer device not available !\n");	return MMSYSERR_NOTENABLED;    }    if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) {	WARN("unable to read mixer !\n");	return MMSYSERR_NOTENABLED;    }    close(mixer);#else    volume = 0x2020;#endif    left = LOBYTE(volume);    right = HIBYTE(volume);    TRACE("left=%ld right=%ld !\n", left, right);    *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) << 16);    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodSetVolume			[internal] */static DWORD wodSetVolume(WORD wDevID, DWORD dwParam){#if 0    int 	mixer;#endif    int		volume;    DWORD	left, right;    TRACE("(%u, %08lX);\n", wDevID, dwParam);    left  = (LOWORD(dwParam) * 100) / 0xFFFFl;    right = (HIWORD(dwParam) * 100) / 0xFFFFl;    volume = left + (right << 8);#if 0    TODO;    if ((mixer = open(MIXER_DEV, O_WRONLY|O_NDELAY)) < 0) {	WARN("mixer device not available !\n");	return MMSYSERR_NOTENABLED;    }    if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {	WARN("unable to set mixer !\n");	return MMSYSERR_NOTENABLED;    } else {	TRACE("volume=%04x\n", (unsigned)volume);    }    close(mixer);#endif    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodGetNumDevs			[internal] */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_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);

⌨️ 快捷键说明

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