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

📄 mciwave.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 4 页
字号:
/* -*- tab-width: 8; c-basic-offset: 4 -*- *//* * Sample Wine Driver for MCI wave forms * * Copyright 	1994 Martin Ayotte *		1999,2000 Eric Pouech *              2000 Francois Jacques * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <stdarg.h>#include "winerror.h"#include "windef.h"#include "winbase.h"#include "wingdi.h"#include "winuser.h"#include "mmddk.h"#include "wownt32.h"#include "digitalv.h"#include "wine/debug.h"WINE_DEFAULT_DEBUG_CHANNEL(mciwave);typedef struct {    UINT			wDevID;    HANDLE			hWave;    int				nUseCount;	/* Incremented for each shared open */    BOOL			fShareable;	/* TRUE if first open was shareable */    HMMIO			hFile;		/* mmio file handle open as Element */    MCI_WAVE_OPEN_PARMSA 	openParms;    WAVEFORMATEX		wfxRef;    LPWAVEFORMATEX		lpWaveFormat;    BOOL			fInput;		/* FALSE = Output, TRUE = Input */    volatile WORD		dwStatus;	/* one from MCI_MODE_xxxx */    DWORD			dwMciTimeFormat;/* One of the supported MCI_FORMAT_xxxx */    DWORD			dwPosition;	/* position in bytes in chunk */    HANDLE			hEvent;		/* for synchronization */    DWORD			dwEventCount;	/* for synchronization */    BOOL                       	bTemporaryFile; /* temporary file (MCI_RECORD) */    MMCKINFO                   	ckMainRIFF;     /* main RIFF chunk */    MMCKINFO                   	ckWaveData;     /* data chunk */} WINE_MCIWAVE;/* =================================================================== * =================================================================== * FIXME: should be using the new mmThreadXXXX functions from WINMM * instead of those * it would require to add a wine internal flag to mmThreadCreate * in order to pass a 32 bit function instead of a 16 bit one * =================================================================== * =================================================================== */struct SCA {    UINT 	wDevID;    UINT 	wMsg;    DWORD 	dwParam1;    DWORD 	dwParam2;};/************************************************************************** * 				MCI_SCAStarter			[internal] */static DWORD CALLBACK	MCI_SCAStarter(LPVOID arg){    struct SCA*	sca = (struct SCA*)arg;    DWORD		ret;    TRACE("In thread before async command (%08x,%u,%08lx,%08lx)\n",	  sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);    ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);    TRACE("In thread after async command (%08x,%u,%08lx,%08lx)\n",	  sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);    HeapFree(GetProcessHeap(), 0, sca);    ExitThread(ret);    WARN("Should not happen ? what's wrong \n");    /* should not go after this point */    return ret;}/************************************************************************** * 				MCI_SendCommandAsync		[internal] */static	DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD dwParam1,				   DWORD dwParam2, UINT size){    struct SCA*	sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA) + size);    if (sca == 0)	return MCIERR_OUT_OF_MEMORY;    sca->wDevID   = wDevID;    sca->wMsg     = wMsg;    sca->dwParam1 = dwParam1;    if (size && dwParam2) {	sca->dwParam2 = (DWORD)sca + sizeof(struct SCA);	/* copy structure passed by program in dwParam2 to be sure	 * we can still use it whatever the program does	 */	memcpy((LPVOID)sca->dwParam2, (LPVOID)dwParam2, size);    } else {	sca->dwParam2 = dwParam2;    }    if (CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL) == 0) {	WARN("Couldn't allocate thread for async command handling, sending synchonously\n");	return MCI_SCAStarter(&sca);    }    return 0;}/*======================================================================* *                  	    MCI WAVE implemantation			* *======================================================================*/static DWORD WAVE_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);/************************************************************************** * 				MCIWAVE_drvOpen			[internal] */static	DWORD	WAVE_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp){    WINE_MCIWAVE*	wmw;    if (modp == NULL) return 0xFFFFFFFF;    wmw = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIWAVE));    if (!wmw)	return 0;    wmw->wDevID = modp->wDeviceID;    mciSetDriverData(wmw->wDevID, (DWORD)wmw);    modp->wCustomCommandTable = MCI_NO_COMMAND_TABLE;    modp->wType = MCI_DEVTYPE_WAVEFORM_AUDIO;    wmw->wfxRef.wFormatTag     	= WAVE_FORMAT_PCM;    wmw->wfxRef.nChannels       = 1;      /* MONO */    wmw->wfxRef.nSamplesPerSec  = 11025;    wmw->wfxRef.nAvgBytesPerSec = 11025;    wmw->wfxRef.nBlockAlign     = 1;    wmw->wfxRef.wBitsPerSample  = 8;    wmw->wfxRef.cbSize          = 0;      /* don't care */    return modp->wDeviceID;}/************************************************************************** * 				MCIWAVE_drvClose		[internal] */static	DWORD	WAVE_drvClose(DWORD dwDevID){    WINE_MCIWAVE*  wmw = (WINE_MCIWAVE*)mciGetDriverData(dwDevID);    if (wmw) {	HeapFree(GetProcessHeap(), 0, wmw);	mciSetDriverData(dwDevID, 0);	return 1;    }    return (dwDevID == 0xFFFFFFFF) ? 1 : 0;}/************************************************************************** * 				WAVE_mciGetOpenDev		[internal] */static WINE_MCIWAVE*  WAVE_mciGetOpenDev(UINT wDevID){    WINE_MCIWAVE*	wmw = (WINE_MCIWAVE*)mciGetDriverData(wDevID);    if (wmw == NULL || wmw->nUseCount == 0) {	WARN("Invalid wDevID=%u\n", wDevID);	return 0;    }    return wmw;}/************************************************************************** * 				WAVE_ConvertByteToTimeFormat	[internal] */static	DWORD 	WAVE_ConvertByteToTimeFormat(WINE_MCIWAVE* wmw, DWORD val, LPDWORD lpRet){    DWORD	   ret = 0;    switch (wmw->dwMciTimeFormat) {    case MCI_FORMAT_MILLISECONDS:	ret = MulDiv(val,1000,wmw->lpWaveFormat->nAvgBytesPerSec);	break;    case MCI_FORMAT_BYTES:	ret = val;	break;    case MCI_FORMAT_SAMPLES: /* FIXME: is this correct ? */	ret = (val * 8) / wmw->lpWaveFormat->wBitsPerSample;	break;    default:	WARN("Bad time format %lu!\n", wmw->dwMciTimeFormat);    }    TRACE("val=%lu=0x%08lx [tf=%lu] => ret=%lu\n", val, val, wmw->dwMciTimeFormat, ret);    *lpRet = 0;    return ret;}/************************************************************************** * 				WAVE_ConvertTimeFormatToByte	[internal] */static	DWORD 	WAVE_ConvertTimeFormatToByte(WINE_MCIWAVE* wmw, DWORD val){    DWORD	ret = 0;    switch (wmw->dwMciTimeFormat) {    case MCI_FORMAT_MILLISECONDS:	ret = (val * wmw->lpWaveFormat->nAvgBytesPerSec) / 1000;	break;    case MCI_FORMAT_BYTES:	ret = val;	break;    case MCI_FORMAT_SAMPLES: /* FIXME: is this correct ? */	ret = (val * wmw->lpWaveFormat->wBitsPerSample) / 8;	break;    default:	WARN("Bad time format %lu!\n", wmw->dwMciTimeFormat);    }    TRACE("val=%lu=0x%08lx [tf=%lu] => ret=%lu\n", val, val, wmw->dwMciTimeFormat, ret);    return ret;}/************************************************************************** * 			WAVE_mciReadFmt	                        [internal] */static	DWORD WAVE_mciReadFmt(WINE_MCIWAVE* wmw, MMCKINFO* pckMainRIFF){    MMCKINFO	mmckInfo;    long	r;    mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');    if (mmioDescend(wmw->hFile, &mmckInfo, pckMainRIFF, MMIO_FINDCHUNK) != 0)	return MCIERR_INVALID_FILE;    TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",	  (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType, mmckInfo.cksize);    wmw->lpWaveFormat = HeapAlloc(GetProcessHeap(), 0, mmckInfo.cksize);    if (!wmw->lpWaveFormat) return MMSYSERR_NOMEM;    r = mmioRead(wmw->hFile, (HPSTR)wmw->lpWaveFormat, mmckInfo.cksize);    if (r < sizeof(WAVEFORMAT))	return MCIERR_INVALID_FILE;    TRACE("wFormatTag=%04X !\n",   wmw->lpWaveFormat->wFormatTag);    TRACE("nChannels=%d \n",       wmw->lpWaveFormat->nChannels);    TRACE("nSamplesPerSec=%ld\n",  wmw->lpWaveFormat->nSamplesPerSec);    TRACE("nAvgBytesPerSec=%ld\n", wmw->lpWaveFormat->nAvgBytesPerSec);    TRACE("nBlockAlign=%d \n",     wmw->lpWaveFormat->nBlockAlign);    TRACE("wBitsPerSample=%u !\n", wmw->lpWaveFormat->wBitsPerSample);    if (r >= (long)sizeof(WAVEFORMATEX))	TRACE("cbSize=%u !\n", wmw->lpWaveFormat->cbSize);    mmioAscend(wmw->hFile, &mmckInfo, 0);    wmw->ckWaveData.ckid = mmioFOURCC('d', 'a', 't', 'a');    if (mmioDescend(wmw->hFile, &wmw->ckWaveData, pckMainRIFF, MMIO_FINDCHUNK) != 0) {	TRACE("can't find data chunk\n");	return MCIERR_INVALID_FILE;    }    TRACE("Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",	  (LPSTR)&wmw->ckWaveData.ckid, (LPSTR)&wmw->ckWaveData.fccType, wmw->ckWaveData.cksize);    TRACE("nChannels=%d nSamplesPerSec=%ld\n",	  wmw->lpWaveFormat->nChannels, wmw->lpWaveFormat->nSamplesPerSec);    return 0;}/************************************************************************** * 			WAVE_mciCreateRIFFSkeleton              [internal] */static DWORD WAVE_mciCreateRIFFSkeleton(WINE_MCIWAVE* wmw){   MMCKINFO     ckWaveFormat;   LPMMCKINFO   lpckRIFF     = &(wmw->ckMainRIFF);   LPMMCKINFO   lpckWaveData = &(wmw->ckWaveData);   lpckRIFF->ckid    = FOURCC_RIFF;   lpckRIFF->fccType = mmioFOURCC('W', 'A', 'V', 'E');   lpckRIFF->cksize  = 0;   if (MMSYSERR_NOERROR != mmioCreateChunk(wmw->hFile, lpckRIFF, MMIO_CREATERIFF))	goto err;   ckWaveFormat.fccType = 0;   ckWaveFormat.ckid    = mmioFOURCC('f', 'm', 't', ' ');   ckWaveFormat.cksize  = sizeof(PCMWAVEFORMAT);   if (!wmw->lpWaveFormat)   {       wmw->lpWaveFormat = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*wmw->lpWaveFormat));       if (!wmw->lpWaveFormat) return MMSYSERR_NOMEM;       memcpy(wmw->lpWaveFormat, &wmw->wfxRef, sizeof(wmw->wfxRef));   }   /* we can only record PCM files... there is no way in the MCI API to specify    * the necessary data to initialize the extra bytes of the WAVEFORMATEX    * structure    */   if (wmw->lpWaveFormat->wFormatTag != WAVE_FORMAT_PCM)       goto err;   if (MMSYSERR_NOERROR != mmioCreateChunk(wmw->hFile, &ckWaveFormat, 0))	goto err;   if (-1 == mmioWrite(wmw->hFile, (HPCSTR)wmw->lpWaveFormat, sizeof(PCMWAVEFORMAT)))	goto err;   if (MMSYSERR_NOERROR != mmioAscend(wmw->hFile, &ckWaveFormat, 0))	goto err;   lpckWaveData->cksize  = 0;   lpckWaveData->fccType = 0;   lpckWaveData->ckid    = mmioFOURCC('d', 'a', 't', 'a');   /* create data chunk */   if (MMSYSERR_NOERROR != mmioCreateChunk(wmw->hFile, lpckWaveData, 0))	goto err;   return 0;err:   if (wmw->lpWaveFormat)       HeapFree(GetProcessHeap(), 0, wmw->lpWaveFormat);   wmw->lpWaveFormat = NULL;   return MCIERR_INVALID_FILE;}/************************************************************************** * 			WAVE_mciOpen	                        [internal] */static DWORD WAVE_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_WAVE_OPEN_PARMSA lpOpenParms){    DWORD		dwRet = 0;    WINE_MCIWAVE*	wmw = (WINE_MCIWAVE*)mciGetDriverData(wDevID);    CHAR*               pszTmpFileName = 0;    TRACE("(%04X, %08lX, %p)\n", wDevID, dwFlags, lpOpenParms);    if (lpOpenParms == NULL)	return MCIERR_NULL_PARAMETER_BLOCK;    if (wmw == NULL) 		return MCIERR_INVALID_DEVICE_ID;    if (dwFlags & MCI_OPEN_SHAREABLE)	return MCIERR_HARDWARE;    if (wmw->nUseCount > 0) {	/* The driver is already opened on this channel	 * Wave driver cannot be shared	 */	return MCIERR_DEVICE_OPEN;    }    wmw->nUseCount++;    wmw->fInput = FALSE;    wmw->hWave = 0;    wmw->dwStatus = MCI_MODE_NOT_READY;    TRACE("wDevID=%04X (lpParams->wDeviceID=%08X)\n", wDevID, lpOpenParms->wDeviceID);    if (dwFlags & MCI_OPEN_ELEMENT) {	if (dwFlags & MCI_OPEN_ELEMENT_ID) {	    /* could it be that (DWORD)lpOpenParms->lpstrElementName	     * contains the hFile value ?	     */	    dwRet = MCIERR_UNRECOGNIZED_COMMAND;	} else {	    if (strlen(lpOpenParms->lpstrElementName) > 0) {	        lpOpenParms->lpstrElementName = lpOpenParms->lpstrElementName;		/* FIXME : what should be done id wmw->hFile is already != 0, or the driver is playin' */		TRACE("MCI_OPEN_ELEMENT '%s' !\n", lpOpenParms->lpstrElementName);		if (lpOpenParms->lpstrElementName && (strlen(lpOpenParms->lpstrElementName) > 0)) {		    wmw->hFile = mmioOpenA((LPSTR)lpOpenParms->lpstrElementName, NULL,				    MMIO_ALLOCBUF | MMIO_DENYWRITE | MMIO_READWRITE);		    if (wmw->hFile == 0) {			WARN("can't find file='%s' !\n", lpOpenParms->lpstrElementName);			dwRet = MCIERR_FILE_NOT_FOUND;		    }		    else		    {			LPMMCKINFO          lpckMainRIFF = &wmw->ckMainRIFF;			/* make sure we're are the beginning of the file */			mmioSeek(wmw->hFile, 0, SEEK_SET);			/* first reading of this file. read the waveformat chunk */			if (mmioDescend(wmw->hFile, lpckMainRIFF, NULL, 0) != 0) {			    dwRet = MCIERR_INVALID_FILE;			} else {			    TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",				(LPSTR)&(lpckMainRIFF->ckid),				(LPSTR) &(lpckMainRIFF->fccType),				(lpckMainRIFF->cksize));			    if ((lpckMainRIFF->ckid    != FOURCC_RIFF) ||				 lpckMainRIFF->fccType != mmioFOURCC('W', 'A', 'V', 'E')) {				dwRet = MCIERR_INVALID_FILE;			    } else {				dwRet = WAVE_mciReadFmt(wmw, lpckMainRIFF);			    }

⌨️ 快捷键说明

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