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

📄 mciwave.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 4 页
字号:
	    		}		    }		}		else {		    wmw->hFile = 0;		}	    }	    else {		CHAR  szTmpPath[MAX_PATH];		CHAR  szPrefix[4]    = "TMP\0";		pszTmpFileName = HeapAlloc(GetProcessHeap(),				           HEAP_ZERO_MEMORY,					   MAX_PATH * sizeof(*pszTmpFileName));		if (!GetTempPathA(sizeof(szTmpPath), szTmpPath)) {		    WARN("can't retrieve temp path!\n");		    HeapFree(GetProcessHeap(), 0, pszTmpFileName);		    return MCIERR_FILE_NOT_FOUND;		}		if (!GetTempFileNameA(szTmpPath, szPrefix, 0, pszTmpFileName)) {			WARN("can't retrieve temp file name!\n");			HeapFree(GetProcessHeap(), 0, pszTmpFileName);			return MCIERR_FILE_NOT_FOUND;		}		wmw->bTemporaryFile = TRUE;		TRACE("MCI_OPEN_ELEMENT '%s' !\n", pszTmpFileName);		if (pszTmpFileName && (strlen(pszTmpFileName) > 0)) {		    wmw->hFile = mmioOpenA(pszTmpFileName, NULL,				           MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_CREATE);		    if (wmw->hFile == 0) {			/* temporary file could not be created. clean filename. */			HeapFree(GetProcessHeap(), 0, pszTmpFileName);			WARN("can't create file='%s' !\n", pszTmpFileName);			dwRet = MCIERR_FILE_NOT_FOUND;		    }		}	    }	}    }    TRACE("hFile=%p\n", wmw->hFile);    memcpy(&wmw->openParms, lpOpenParms, sizeof(MCI_WAVE_OPEN_PARMSA));    if (wmw->bTemporaryFile == TRUE)    {	    /* Additional openParms is temporary file's name */	    wmw->openParms.lpstrElementName = pszTmpFileName;    }    if (dwRet == 0) {	if (wmw->lpWaveFormat) {	    switch (wmw->lpWaveFormat->wFormatTag) {	    case WAVE_FORMAT_PCM:		if (wmw->lpWaveFormat->nAvgBytesPerSec !=		    wmw->lpWaveFormat->nSamplesPerSec * wmw->lpWaveFormat->nBlockAlign) {		    WARN("Incorrect nAvgBytesPerSec (%ld), setting it to %ld\n",			wmw->lpWaveFormat->nAvgBytesPerSec,			wmw->lpWaveFormat->nSamplesPerSec *			 wmw->lpWaveFormat->nBlockAlign);		    wmw->lpWaveFormat->nAvgBytesPerSec =			wmw->lpWaveFormat->nSamplesPerSec *			wmw->lpWaveFormat->nBlockAlign;		}		break;	    }	}	wmw->dwPosition = 0;	wmw->dwStatus = MCI_MODE_STOP;    } else {	wmw->nUseCount--;	if (wmw->hFile != 0)	    mmioClose(wmw->hFile, 0);	wmw->hFile = 0;    }    return dwRet;}/************************************************************************** *                               WAVE_mciCue             [internal] */static DWORD WAVE_mciCue(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms){    /*      FIXME      This routine is far from complete. At the moment only a check is done on the      MCI_WAVE_INPUT flag. No explicit check on MCI_WAVE_OUTPUT is done since that      is the default.      The flags MCI_NOTIFY (and the callback parameter in lpParms) and MCI_WAIT      are ignored    */    DWORD		dwRet;    WINE_MCIWAVE*	wmw = WAVE_mciGetOpenDev(wDevID);    FIXME("(%u, %08lX, %p); likely to fail\n", wDevID, dwParam, lpParms);    if (wmw == NULL)	return MCIERR_INVALID_DEVICE_ID;    /* always close elements ? */    if (wmw->hFile != 0) {	mmioClose(wmw->hFile, 0);	wmw->hFile = 0;    }    dwRet = MMSYSERR_NOERROR;  /* assume success */    if ((dwParam & MCI_WAVE_INPUT) && !wmw->fInput) {	dwRet = waveOutClose(wmw->hWave);	if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;	wmw->fInput = TRUE;    } else if (wmw->fInput) {	dwRet = waveInClose(wmw->hWave);	if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;	wmw->fInput = FALSE;    }    wmw->hWave = 0;    return (dwRet == MMSYSERR_NOERROR) ? 0 : MCIERR_INTERNAL;}/************************************************************************** * 				WAVE_mciStop			[internal] */static DWORD WAVE_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms){    DWORD 		dwRet = 0;    WINE_MCIWAVE*	wmw = WAVE_mciGetOpenDev(wDevID);    TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);    if (wmw == NULL)		return MCIERR_INVALID_DEVICE_ID;    /* wait for playback thread (if any) to exit before processing further */    switch (wmw->dwStatus) {    case MCI_MODE_PAUSE:    case MCI_MODE_PLAY:    case MCI_MODE_RECORD:	{	    int oldStat = wmw->dwStatus;	    wmw->dwStatus = MCI_MODE_NOT_READY;	    if (oldStat == MCI_MODE_PAUSE)		dwRet = (wmw->fInput) ? waveInReset(wmw->hWave) : waveOutReset(wmw->hWave);	}	while (wmw->dwStatus != MCI_MODE_STOP)	    Sleep(10);	break;    }    wmw->dwPosition = 0;    /* sanity resets */    wmw->dwStatus = MCI_MODE_STOP;    if ((dwFlags & MCI_NOTIFY) && lpParms) {	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),			wmw->openParms.wDeviceID, MCI_NOTIFY_SUCCESSFUL);    }    return dwRet;}/************************************************************************** *				WAVE_mciClose		[internal] */static DWORD WAVE_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms){    DWORD		dwRet = 0;    WINE_MCIWAVE*	wmw = WAVE_mciGetOpenDev(wDevID);    TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);    if (wmw == NULL)		return MCIERR_INVALID_DEVICE_ID;    if (wmw->dwStatus != MCI_MODE_STOP) {	dwRet = WAVE_mciStop(wDevID, MCI_WAIT, lpParms);    }    wmw->nUseCount--;    if (wmw->nUseCount == 0) {	if (wmw->hFile != 0) {	    mmioClose(wmw->hFile, 0);	    wmw->hFile = 0;	}    }    /* That string got allocated in mciOpen because no filename was specified     * in MCI_OPEN_PARMS stucture. Cast-away const from string since it was     * allocated by mciOpen, *NOT* the application.     */    if (wmw->bTemporaryFile)    {	HeapFree(GetProcessHeap(), 0, (char*)wmw->openParms.lpstrElementName);	wmw->openParms.lpstrElementName = NULL;    }    HeapFree(GetProcessHeap(), 0, wmw->lpWaveFormat);    wmw->lpWaveFormat = NULL;    if ((dwFlags & MCI_NOTIFY) && lpParms) {	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),			wmw->openParms.wDeviceID,			(dwRet == 0) ? MCI_NOTIFY_SUCCESSFUL : MCI_NOTIFY_FAILURE);    }    return 0;}/************************************************************************** * 				WAVE_mciPlayCallback		[internal] */static	void	CALLBACK WAVE_mciPlayCallback(HWAVEOUT hwo, UINT uMsg,					      DWORD dwInstance,					      DWORD dwParam1, DWORD dwParam2){    WINE_MCIWAVE*	wmw = (WINE_MCIWAVE*)dwInstance;    switch (uMsg) {    case WOM_OPEN:    case WOM_CLOSE:	break;    case WOM_DONE:	InterlockedIncrement(&wmw->dwEventCount);	TRACE("Returning waveHdr=%lx\n", dwParam1);	SetEvent(wmw->hEvent);	break;    default:	ERR("Unknown uMsg=%d\n", uMsg);    }}/****************************************************************** *		WAVE_mciPlayWaitDone * * */static void WAVE_mciPlayWaitDone(WINE_MCIWAVE* wmw){    for (;;) {	ResetEvent(wmw->hEvent);	if (InterlockedDecrement(&wmw->dwEventCount) >= 0) {	    break;	}	InterlockedIncrement(&wmw->dwEventCount);	WaitForSingleObject(wmw->hEvent, INFINITE);    }}/************************************************************************** * 				WAVE_mciPlay		[internal] */static DWORD WAVE_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms){    DWORD		end;    LONG		bufsize, count, left;    DWORD		dwRet = 0;    LPWAVEHDR		waveHdr = NULL;    WINE_MCIWAVE*	wmw = WAVE_mciGetOpenDev(wDevID);    int			whidx;    TRACE("(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);    if (wmw == NULL)		return MCIERR_INVALID_DEVICE_ID;    if (lpParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;    /* FIXME : since there is no way to determine in which mode the device is     * open (recording/playback) automatically switch from a mode to another     */    wmw->fInput = FALSE;    if (wmw->fInput) {	WARN("cannot play on input device\n");	return MCIERR_NONAPPLICABLE_FUNCTION;    }    if (wmw->hFile == 0) {	WARN("Can't play: no file='%s' !\n", wmw->openParms.lpstrElementName);	return MCIERR_FILE_NOT_FOUND;    }    if (wmw->dwStatus == MCI_MODE_PAUSE) {	/* FIXME: parameters (start/end) in lpParams may not be used */	return WAVE_mciResume(wDevID, dwFlags, (LPMCI_GENERIC_PARMS)lpParms);    }    /** This function will be called again by a thread when async is used.     * We have to set MCI_MODE_PLAY before we do this so that the app can spin     * on MCI_STATUS, so we have to allow it here if we're not going to start this thread.     */    if ((wmw->dwStatus != MCI_MODE_STOP) && ((wmw->dwStatus != MCI_MODE_PLAY) && (dwFlags & MCI_WAIT))) {	return MCIERR_INTERNAL;    }    wmw->dwStatus = MCI_MODE_PLAY;    if (!(dwFlags & MCI_WAIT)) {	return MCI_SendCommandAsync(wmw->openParms.wDeviceID, MCI_PLAY, dwFlags,				    (DWORD)lpParms, sizeof(MCI_PLAY_PARMS));    }    end = 0xFFFFFFFF;    if (lpParms && (dwFlags & MCI_FROM)) {	wmw->dwPosition = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwFrom);    }    if (lpParms && (dwFlags & MCI_TO)) {	end = WAVE_ConvertTimeFormatToByte(wmw, lpParms->dwTo);    }    TRACE("Playing from byte=%lu to byte=%lu\n", wmw->dwPosition, end);    if (end <= wmw->dwPosition)	return TRUE;#define	WAVE_ALIGN_ON_BLOCK(wmw,v) \((((v) + (wmw)->lpWaveFormat->nBlockAlign - 1) / (wmw)->lpWaveFormat->nBlockAlign) * (wmw)->lpWaveFormat->nBlockAlign)    wmw->dwPosition        = WAVE_ALIGN_ON_BLOCK(wmw, wmw->dwPosition);    wmw->ckWaveData.cksize = WAVE_ALIGN_ON_BLOCK(wmw, wmw->ckWaveData.cksize);    if (dwRet == 0) {	if (wmw->lpWaveFormat) {	    switch (wmw->lpWaveFormat->wFormatTag) {	    case WAVE_FORMAT_PCM:		if (wmw->lpWaveFormat->nAvgBytesPerSec !=		    wmw->lpWaveFormat->nSamplesPerSec * wmw->lpWaveFormat->nBlockAlign) {		    WARN("Incorrect nAvgBytesPerSec (%ld), setting it to %ld\n",			wmw->lpWaveFormat->nAvgBytesPerSec,			wmw->lpWaveFormat->nSamplesPerSec *			 wmw->lpWaveFormat->nBlockAlign);		    wmw->lpWaveFormat->nAvgBytesPerSec =			wmw->lpWaveFormat->nSamplesPerSec *			wmw->lpWaveFormat->nBlockAlign;		}		break;	    }	}    } else {	TRACE("can't retrieve wave format %ld\n", dwRet);	goto cleanUp;    }    /* go back to beginning of chunk plus the requested position */    /* FIXME: I'm not sure this is correct, notably because some data linked to     * the decompression state machine will not be correcly initialized.     * try it this way (other way would be to decompress from 0 up to dwPosition     * and to start sending to hWave when dwPosition is reached)     */    mmioSeek(wmw->hFile, wmw->ckWaveData.dwDataOffset + wmw->dwPosition, SEEK_SET); /* >= 0 */    /* By default the device will be opened for output, the MCI_CUE function is there to     * change from output to input and back     */    /* FIXME: how to choose between several output channels ? here mapper is forced */    dwRet = waveOutOpen((HWAVEOUT *)&wmw->hWave, WAVE_MAPPER, wmw->lpWaveFormat,			(DWORD)WAVE_mciPlayCallback, (DWORD)wmw, CALLBACK_FUNCTION);    if (dwRet != 0) {	TRACE("Can't open low level audio device %ld\n", dwRet);	dwRet = MCIERR_DEVICE_OPEN;	wmw->hWave = 0;	goto cleanUp;    }    /* make it so that 3 buffers per second are needed */    bufsize = WAVE_ALIGN_ON_BLOCK(wmw, wmw->lpWaveFormat->nAvgBytesPerSec / 3);    waveHdr = HeapAlloc(GetProcessHeap(), 0, 2 * sizeof(WAVEHDR) + 2 * bufsize);    waveHdr[0].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR);    waveHdr[1].lpData = (char*)waveHdr + 2 * sizeof(WAVEHDR) + bufsize;    waveHdr[0].dwUser         = waveHdr[1].dwUser         = 0L;    waveHdr[0].dwLoops        = waveHdr[1].dwLoops        = 0L;    waveHdr[0].dwFlags        = waveHdr[1].dwFlags        = 0L;    waveHdr[0].dwBufferLength = waveHdr[1].dwBufferLength = bufsize;    if (waveOutPrepareHeader(wmw->hWave, &waveHdr[0], sizeof(WAVEHDR)) ||	waveOutPrepareHeader(wmw->hWave, &waveHdr[1], sizeof(WAVEHDR))) {	dwRet = MCIERR_INTERNAL;	goto cleanUp;    }    whidx = 0;    left = min(wmw->ckWaveData.cksize, end - wmw->dwPosition);    wmw->hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);    wmw->dwEventCount = 1L; /* for first buffer */    TRACE("Playing (normalized) from byte=%lu for %lu bytes\n", wmw->dwPosition, left);    /* FIXME: this doesn't work if wmw->dwPosition != 0 */    while (left > 0 && wmw->dwStatus != MCI_MODE_STOP && wmw->dwStatus != MCI_MODE_NOT_READY) {	count = mmioRead(wmw->hFile, waveHdr[whidx].lpData, min(bufsize, left));	TRACE("mmioRead bufsize=%ld count=%ld\n", bufsize, count);	if (count < 1)	    break;	/* count is always <= bufsize, so this is correct regarding the	 * waveOutPrepareHeader function	 */	waveHdr[whidx].dwBufferLength = count;	waveHdr[whidx].dwFlags &= ~WHDR_DONE;	TRACE("before WODM_WRITE lpWaveHdr=%p dwBufferLength=%lu dwBytesRecorded=%lu\n",	      &waveHdr[whidx], waveHdr[whidx].dwBufferLength,	      waveHdr[whidx].dwBytesRecorded);	dwRet = waveOutWrite(wmw->hWave, &waveHdr[whidx], sizeof(WAVEHDR));	left -= count;	wmw->dwPosition += count;

⌨️ 快捷键说明

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