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

📄 audio.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 3 页
字号:
    if(WOutDev[wDevID].play_stream != (arts_stream_t*)-1)    {      TRACE("device already allocated\n");      return MMSYSERR_ALLOCATED;    }    /* only PCM format is supported so far... */    if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM ||	lpDesc->lpFormat->nChannels == 0 ||	lpDesc->lpFormat->nSamplesPerSec == 0) {	WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",	     lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,	     lpDesc->lpFormat->nSamplesPerSec);	return WAVERR_BADFORMAT;    }    if (dwFlags & WAVE_FORMAT_QUERY) {	TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%ld !\n",	     lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,	     lpDesc->lpFormat->nSamplesPerSec);	return MMSYSERR_NOERROR;    }    wwo = &WOutDev[wDevID];    /* direct sound not supported, ignore the flag */    dwFlags &= ~WAVE_DIRECTSOUND;    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;    }    wwo->play_stream = arts_play_stream(wwo->format.wf.nSamplesPerSec,	wwo->format.wBitsPerSample, wwo->format.wf.nChannels, "winearts");    /* clear these so we don't have any confusion ;-) */    wwo->sound_buffer = 0;    wwo->buffer_size = 0;    arts_stream_set(wwo->play_stream, ARTS_P_BLOCKING, 0);    /* disable blocking on this stream */    if(!wwo->play_stream) return MMSYSERR_ALLOCATED;    /* Try to set buffer size from constant and store the value that it	was set to for future use */    wwo->dwBufferSize = arts_stream_set(wwo->play_stream,		ARTS_P_BUFFER_SIZE, BUFFER_SIZE);    TRACE("Tried to set BUFFER_SIZE of %d, wwo->dwBufferSize is actually %ld\n", BUFFER_SIZE, wwo->dwBufferSize);    wwo->dwPlayedTotal = 0;    wwo->dwWrittenTotal = 0;    /* Initialize volume to full level */    wwo->volume_left = 100;    wwo->volume_right = 100;    ARTS_InitRingMessage(&wwo->msgRing);    /* create player thread */    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("stream=0x%lx, dwBufferSize=%ld\n",	  (long)wwo->play_stream, wwo->dwBufferSize);    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].play_stream  ==	(arts_stream_t*)-1)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    wwo = &WOutDev[wDevID];    if (wwo->lpQueuePtr) {	WARN("buffers still playing !\n");	ret = WAVERR_STILLPLAYING;    } else {	TRACE("imhere[3-close]\n");	if (wwo->hThread != INVALID_HANDLE_VALUE) {	    ARTS_AddRingMessage(&wwo->msgRing, WINE_WM_CLOSING, 0, TRUE);	}        ARTS_DestroyRingMessage(&wwo->msgRing);	ARTS_CloseDevice(wwo);	/* close the stream and clean things up */	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].play_stream ==		(arts_stream_t*)-1)    {        WARN("bad dev ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (lpWaveHdr->lpData == NULL || !(lpWaveHdr->dwFlags & WHDR_PREPARED))    {	TRACE("unprepared\n");	return WAVERR_UNPREPARED;    }    if (lpWaveHdr->dwFlags & WHDR_INQUEUE)    {	TRACE("still playing\n");	return WAVERR_STILLPLAYING;    }    lpWaveHdr->dwFlags &= ~WHDR_DONE;    lpWaveHdr->dwFlags |= WHDR_INQUEUE;    lpWaveHdr->lpNext = 0;    TRACE("adding ring message\n");    ARTS_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].play_stream ==		(arts_stream_t*)-1)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    TRACE("imhere[3-PAUSING]\n");    ARTS_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].play_stream ==		(arts_stream_t*)-1)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (WOutDev[wDevID].state == WINE_WS_PAUSED) {	TRACE("imhere[3-RESTARTING]\n");	ARTS_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].play_stream ==	(arts_stream_t*)-1)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    TRACE("imhere[3-RESET]\n");    ARTS_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].play_stream ==	(arts_stream_t*)-1)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    if (lpTime == NULL)	return MMSYSERR_INVALPARAM;    wwo = &WOutDev[wDevID];    ARTS_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].play_stream ==		(arts_stream_t*)-1)    {	WARN("bad device ID !\n");	return MMSYSERR_BADDEVICEID;    }    ARTS_AddRingMessage(&WOutDev[wDevID].msgRing, WINE_WM_BREAKLOOP, 0, TRUE);    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodGetVolume			[internal] */static DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol){    DWORD left, right;    left = WOutDev[wDevID].volume_left;    right = WOutDev[wDevID].volume_right;    TRACE("(%u, %p);\n", wDevID, lpdwVol);    *lpdwVol = ((left * 0xFFFFl) / 100) + (((right * 0xFFFFl) / 100) <<		16);    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodSetVolume			[internal] */static DWORD wodSetVolume(WORD wDevID, DWORD dwParam){    DWORD left, right;    left  = (LOWORD(dwParam) * 100) / 0xFFFFl;    right = (HIWORD(dwParam) * 100) / 0xFFFFl;    TRACE("(%u, %08lX);\n", wDevID, dwParam);    WOutDev[wDevID].volume_left = left;    WOutDev[wDevID].volume_right = right;    return MMSYSERR_NOERROR;}/************************************************************************** * 				wodGetNumDevs			[internal] */static	DWORD	wodGetNumDevs(void){    return MAX_WAVEOUTDRV;}/************************************************************************** * 				wodMessage (WINEARTS.@) */DWORD WINAPI ARTS_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);    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);    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			* *======================================================================*/static DWORD wodDsCreate(UINT wDevID, PIDSDRIVER* drv){    /* we can't perform memory mapping as we don't have a file stream	interface with arts like we do with oss */    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;}static DWORD wodDsDesc(UINT wDevID, PDSDRIVERDESC desc){    memset(desc, 0, sizeof(*desc));    strcpy(desc->szDesc, "Wine aRts DirectSound Driver");    strcpy(desc->szDrvName, "winearts.drv");    return MMSYSERR_NOERROR;}static DWORD wodDsGuid(UINT wDevID, LPGUID pGuid){    memcpy(pGuid, &DSDEVID_DefaultPlayback, sizeof(GUID));    return MMSYSERR_NOERROR;}#else /* !HAVE_ARTS *//************************************************************************** * 				wodMessage (WINEARTS.@) */DWORD WINAPI ARTS_wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,			    DWORD dwParam1, DWORD dwParam2){    FIXME("(%u, %04X, %08lX, %08lX, %08lX):stub\n", wDevID, wMsg, dwUser, dwParam1, dwParam2);    return MMSYSERR_NOTENABLED;}#endif /* HAVE_ARTS */

⌨️ 快捷键说明

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