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

📄 audio.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 5 页
字号:
    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;    }    /* Read output space info for future reference */    if (ioctl(wwo->ossdev->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {	ERR("ioctl(%s, SNDCTL_DSP_GETOSPACE) failed (%s)\n", wwo->ossdev->dev_name, strerror(errno));        OSS_CloseDevice(wwo->ossdev);	wwo->state = WINE_WS_CLOSED;	return MMSYSERR_NOTENABLED;    }    /* Check that fragsize is correct per our settings above */    if ((info.fragsize > 1024) && (LOWORD(audio_fragment) <= 10)) {	/* we've tried to set 1K fragments or less, but it didn't work */	ERR("fragment size set failed, size is now %d\n", info.fragsize);	MESSAGE("Your Open Sound System driver did not let us configure small enough sound fragments.\n");	MESSAGE("This may cause delays and other problems in audio playback with certain applications.\n");    }    /* Remember fragsize and total buffer size for future use */    wwo->dwFragmentSize = info.fragsize;    wwo->dwBufferSize = info.fragstotal * info.fragsize;    wwo->dwPlayedTotal = 0;    wwo->dwWrittenTotal = 0;    wwo->bNeedPost = TRUE;    OSS_InitRingMessage(&wwo->msgRing);    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);    wwo->hStartUpEvent = INVALID_HANDLE_VALUE;    TRACE("fd=%d fragmentSize=%ld\n",	  wwo->ossdev->fd, 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 >= numOutDev || WOutDev[wDevID].state == WINE_WS_CLOSED) {	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) {	    OSS_AddRingMessage(&wwo->msgRing, WINE_WM_CLOSING, 0, TRUE);	}	if (wwo->mapping) {	    munmap(wwo->mapping, wwo->maplen);	    wwo->mapping = NULL;	}        OSS_DestroyRingMessage(&wwo->msgRing);        OSS_CloseDevice(wwo->ossdev);	wwo->state = WINE_WS_CLOSED;	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 >= numOutDev || WOutDev[wDevID].state == WINE_WS_CLOSED) {        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;    if ((lpWaveHdr->dwBufferLength & (WOutDev[wDevID].format.wf.nBlockAlign - 1)) != 0)    {        WARN("WaveHdr length isn't a multiple of the PCM block size: %ld %% %d\n",lpWaveHdr->dwBufferLength,WOutDev[wDevID].format.wf.nBlockAlign);        lpWaveHdr->dwBufferLength &= ~(WOutDev[wDevID].format.wf.nBlockAlign - 1);    }    OSS_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 >= numOutDev) {	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 >= numOutDev) {	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 >= numOutDev || WOutDev[wDevID].state == WINE_WS_CLOSED) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    OSS_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 >= numOutDev || WOutDev[wDevID].state == WINE_WS_CLOSED) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    OSS_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 >= numOutDev || WOutDev[wDevID].state == WINE_WS_CLOSED) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    OSS_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 >= numOutDev || WOutDev[wDevID].state == WINE_WS_CLOSED) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (lpTime == NULL)	return MMSYSERR_INVALPARAM;    wwo = &WOutDev[wDevID];#ifdef EXACT_WODPOSITION    OSS_AddRingMessage(&wwo->msgRing, WINE_WM_UPDATE, 0, TRUE);#endif    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 / (60 * 60 * 1000);	time -= lpTime->u.smpte.hour * (60 * 60 * 1000);	lpTime->u.smpte.min = time / (60 * 1000);	time -= lpTime->u.smpte.min * (60 * 1000);	lpTime->u.smpte.sec = time / 1000;	time -= lpTime->u.smpte.sec * 1000;	lpTime->u.smpte.frame = time * 30 / 1000;	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 >= numOutDev || WOutDev[wDevID].state == WINE_WS_CLOSED) {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    OSS_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_BREAKLOOP, 0, TRUE);    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodGetVolume			[internal] */static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol){    int 	mixer;    int		volume;    DWORD	left, right;    TRACE("(%u, %p);\n", wDevID, lpdwVol);    if (lpdwVol == NULL)	return MMSYSERR_NOTENABLED;    if (wDevID >= numOutDev) 	return MMSYSERR_INVALPARAM;    if ((mixer = open(WOutDev[wDevID].ossdev->mixer_name, O_RDONLY|O_NDELAY)) < 0) {	WARN("mixer device not available !\n");	return MMSYSERR_NOTENABLED;    }    if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) {	WARN("ioctl(%s, SOUND_MIXER_READ_PCM) failed (%s)n", WOutDev[wDevID].ossdev->mixer_name, strerror(errno));	return MMSYSERR_NOTENABLED;    }    close(mixer);    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){    int 	mixer;    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 (wDevID >= numOutDev) {	WARN("invalid parameter: wDevID > %d\n", numOutDev);	return MMSYSERR_INVALPARAM;    }    if ((mixer = open(WOutDev[wDevID].ossdev->mixer_name, O_WRONLY|O_NDELAY)) < 0) {	WARN("mixer device not available !\n");	return MMSYSERR_NOTENABLED;    }    if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {	WARN("ioctl(%s, SOUND_MIXER_WRITE_PCM) failed (%s)\n", WOutDev[wDevID].ossdev->mixer_name, strerror(errno));	return MMSYSERR_NOTENABLED;    } else {	TRACE("volume=%04x\n", (unsigned)volume);    }    close(mixer);    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodMessage (WINEOSS.7) */DWORD WINAPI OSS_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)dwPara

⌨️ 快捷键说明

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