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

📄 mcimidi.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 3 页
字号:
 */static DWORD MIDI_mciReadMTrk(WINE_MCIMIDI* wmm, MCI_MIDITRACK* mmt){    DWORD		toberead;    FOURCC		fourcc;    if (mmioRead(wmm->hFile, (HPSTR)&fourcc, (long)sizeof(FOURCC)) !=	(long)sizeof(FOURCC)) {	return MCIERR_INVALID_FILE;    }    if (fourcc != mmioFOURCC('M', 'T', 'r', 'k')) {	WARN("Can't synchronize on 'MTrk' !\n");	return MCIERR_INVALID_FILE;    }    if (MIDI_mciReadLong(wmm, &toberead) != 0) {	return MCIERR_INVALID_FILE;    }    mmt->dwFirst = mmioSeek(wmm->hFile, 0, SEEK_CUR); /* >= 0 */    mmt->dwLast = mmt->dwFirst + toberead;    /* compute # of pulses in this track */    mmt->dwIndex = mmt->dwFirst;    mmt->dwEventPulse = 0;    while (MIDI_mciReadNextEvent(wmm, mmt) == 0 && LOWORD(mmt->dwEventData) != 0x2FFF) {	char	buf[1024];	WORD	len;	mmt->dwIndex += mmt->wEventLength;	switch (LOWORD(mmt->dwEventData)) {	case 0x02FF:	case 0x03FF:	    /* position after meta data header */	    mmioSeek(wmm->hFile, mmt->dwIndex + HIWORD(mmt->dwEventData), SEEK_SET);	    len = mmt->wEventLength - HIWORD(mmt->dwEventData);	    if (len >= sizeof(buf)) {		WARN("Buffer for text is too small (%d bytes, when %u are needed)\n", sizeof(buf) - 1, len);		len = sizeof(buf) - 1;	    }	    if (mmioRead(wmm->hFile, (HPSTR)buf, len) == len) {		buf[len] = 0;	/* end string in case */		switch (HIBYTE(LOWORD(mmt->dwEventData))) {		case 0x02:		    if (wmm->lpstrCopyright) {			WARN("Two copyright notices (%s|%s)\n", wmm->lpstrCopyright, buf);		    } else {                        wmm->lpstrCopyright = HeapAlloc( GetProcessHeap(), 0, strlen(buf)+1 );                        strcpy( wmm->lpstrCopyright, buf );		    }		    break;		case 0x03:		    if (wmm->lpstrName) {			WARN("Two names (%s|%s)\n", wmm->lpstrName, buf);		    } else {			wmm->lpstrName = HeapAlloc( GetProcessHeap(), 0, strlen(buf)+1 );                        strcpy( wmm->lpstrName, buf );		    }		    break;		}	    }	    break;	}    }    mmt->dwLength = mmt->dwEventPulse;    TRACE("Track %u has %lu bytes and %lu pulses\n", mmt->wTrackNr, toberead, mmt->dwLength);    /* reset track data */    mmt->wStatus = 1;	/* ok, playing */    mmt->dwIndex = mmt->dwFirst;    mmt->dwEventPulse = 0;    if (mmioSeek(wmm->hFile, 0, SEEK_CUR) != mmt->dwLast) {	WARN("Ouch, out of sync seek=%lu track=%lu\n",	     mmioSeek(wmm->hFile, 0, SEEK_CUR), mmt->dwLast);	/* position at end of this track, to be ready to read next track */	mmioSeek(wmm->hFile, mmt->dwLast, SEEK_SET);    }    return 0;}/************************************************************************** * 				MIDI_mciReadMThd		[internal] */static DWORD MIDI_mciReadMThd(WINE_MCIMIDI* wmm, DWORD dwOffset){    DWORD	toberead;    FOURCC	fourcc;    WORD	nt;    TRACE("(%p, %08lX);\n", wmm, dwOffset);    if (mmioSeek(wmm->hFile, dwOffset, SEEK_SET) != dwOffset) {	WARN("Can't seek at %08lX begin of 'MThd' \n", dwOffset);	return MCIERR_INVALID_FILE;    }    if (mmioRead(wmm->hFile, (HPSTR)&fourcc,		   (long) sizeof(FOURCC)) != (long) sizeof(FOURCC))	return MCIERR_INVALID_FILE;    if (fourcc != mmioFOURCC('M', 'T', 'h', 'd')) {	WARN("Can't synchronize on 'MThd' !\n");	return MCIERR_INVALID_FILE;    }    if (MIDI_mciReadLong(wmm, &toberead) != 0 || toberead < 3 * sizeof(WORD))	return MCIERR_INVALID_FILE;    if (MIDI_mciReadWord(wmm, &wmm->wFormat) != 0 ||	MIDI_mciReadWord(wmm, &wmm->nTracks) != 0 ||	MIDI_mciReadWord(wmm, &wmm->nDivision) != 0) {	return MCIERR_INVALID_FILE;    }    TRACE("toberead=0x%08lX, wFormat=0x%04X nTracks=0x%04X nDivision=0x%04X\n",	  toberead, wmm->wFormat, wmm->nTracks, wmm->nDivision);    /* MS doc says that the MIDI MCI time format must be put by default to the format     * stored in the MIDI file...     */    if (wmm->nDivision > 0x8000) {	/* eric.pouech@lemel.fr 98/11	 * In did not check this very code (pulses are expressed as SMPTE sub-frames).	 * In about 40 MB of MIDI files I have, none was SMPTE based...	 * I'm just wondering if this is widely used :-). So, if someone has one of	 * these files, I'd like to know about.	 */	FIXME("Handling SMPTE time in MIDI files has not been tested\n"	      "Please report to comp.emulators.ms-windows.wine with MIDI file !\n");	switch (HIBYTE(wmm->nDivision)) {	case 0xE8:	wmm->dwMciTimeFormat = MCI_FORMAT_SMPTE_24;	break;	/* -24 */	case 0xE7:	wmm->dwMciTimeFormat = MCI_FORMAT_SMPTE_25;	break;	/* -25 */	case 0xE3:	wmm->dwMciTimeFormat = MCI_FORMAT_SMPTE_30DROP;	break;	/* -29 */ /* is the MCI constant correct ? */	case 0xE2:	wmm->dwMciTimeFormat = MCI_FORMAT_SMPTE_30;	break;	/* -30 */	default:	    WARN("Unsupported number of frames %d\n", -(char)HIBYTE(wmm->nDivision));	    return MCIERR_INVALID_FILE;	}	switch (LOBYTE(wmm->nDivision)) {	case 4:	/* MIDI Time Code */	case 8:	case 10:	case 80: /* SMPTE bit resolution */	case 100:	default:	    WARN("Unsupported number of sub-frames %d\n", LOBYTE(wmm->nDivision));	    return MCIERR_INVALID_FILE;	}    } else if (wmm->nDivision == 0) {	WARN("Number of division is 0, can't support that !!\n");	return MCIERR_INVALID_FILE;    } else {	wmm->dwMciTimeFormat = MCI_FORMAT_MILLISECONDS;    }    switch (wmm->wFormat) {    case 0:	if (wmm->nTracks != 1) {	    WARN("Got type 0 file whose number of track is not 1. Setting it to 1\n");	    wmm->nTracks = 1;	}	break;    case 1:    case 2:	break;    default:	WARN("Handling MIDI files which format = %d is not (yet) supported\n"	     "Please report with MIDI file !\n", wmm->wFormat);	return MCIERR_INVALID_FILE;    }    if (wmm->nTracks & 0x8000) {	/* this shouldn't be a problem... */	WARN("Ouch !! Implementation limitation to 32k tracks per MIDI file is overflowed\n");	wmm->nTracks = 0x7FFF;    }    if ((wmm->tracks = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_MIDITRACK) * wmm->nTracks)) == NULL) {	return MCIERR_OUT_OF_MEMORY;    }    toberead -= 3 * sizeof(WORD);    if (toberead > 0) {	TRACE("Size of MThd > 6, skipping %ld extra bytes\n", toberead);	mmioSeek(wmm->hFile, toberead, SEEK_CUR);    }    for (nt = 0; nt < wmm->nTracks; nt++) {	wmm->tracks[nt].wTrackNr = nt;	if (MIDI_mciReadMTrk(wmm, &wmm->tracks[nt]) != 0) {	    WARN("Can't read 'MTrk' header \n");	    return MCIERR_INVALID_FILE;	}    }    wmm->dwTempo = 500000;    return 0;}/************************************************************************** * 			MIDI_ConvertPulseToMS			[internal] */static	DWORD	MIDI_ConvertPulseToMS(WINE_MCIMIDI* wmm, DWORD pulse){    DWORD	ret = 0;    /* FIXME: this function may return false values since the tempo (wmm->dwTempo)     * may change during file playing     */    if (wmm->nDivision == 0) {	FIXME("Shouldn't happen. wmm->nDivision = 0\n");    } else if (wmm->nDivision > 0x8000) { /* SMPTE, unchecked FIXME? */	int	nf = -(char)HIBYTE(wmm->nDivision);	/* number of frames     */	int	nsf = LOBYTE(wmm->nDivision);		/* number of sub-frames */	ret = (pulse * 1000) / (nf * nsf);    } else {	ret = (DWORD)((double)pulse * ((double)wmm->dwTempo / 1000) /		      (double)wmm->nDivision);    }    /*      TRACE("pulse=%lu tempo=%lu division=%u=0x%04x => ms=%lu\n",      pulse, wmm->dwTempo, wmm->nDivision, wmm->nDivision, ret);    */    return ret;}#define TIME_MS_IN_ONE_HOUR	(60*60*1000)#define TIME_MS_IN_ONE_MINUTE	(60*1000)#define TIME_MS_IN_ONE_SECOND	(1000)/************************************************************************** * 			MIDI_ConvertTimeFormatToMS		[internal] */static	DWORD	MIDI_ConvertTimeFormatToMS(WINE_MCIMIDI* wmm, DWORD val){    DWORD	ret = 0;    switch (wmm->dwMciTimeFormat) {    case MCI_FORMAT_MILLISECONDS:	ret = val;	break;    case MCI_FORMAT_SMPTE_24:	ret =	    (HIBYTE(HIWORD(val)) * 125) / 3 +             LOBYTE(HIWORD(val)) * TIME_MS_IN_ONE_SECOND +	    HIBYTE(LOWORD(val)) * TIME_MS_IN_ONE_MINUTE + LOBYTE(LOWORD(val)) * TIME_MS_IN_ONE_HOUR;	break;    case MCI_FORMAT_SMPTE_25:	ret =	    HIBYTE(HIWORD(val)) * 40 + 		  	  LOBYTE(HIWORD(val)) * TIME_MS_IN_ONE_SECOND +	    HIBYTE(LOWORD(val)) * TIME_MS_IN_ONE_MINUTE + LOBYTE(LOWORD(val)) * TIME_MS_IN_ONE_HOUR;	break;    case MCI_FORMAT_SMPTE_30:	ret =	    (HIBYTE(HIWORD(val)) * 100) / 3 + 		  LOBYTE(HIWORD(val)) * TIME_MS_IN_ONE_SECOND +	    HIBYTE(LOWORD(val)) * TIME_MS_IN_ONE_MINUTE + LOBYTE(LOWORD(val)) * TIME_MS_IN_ONE_HOUR;	break;    default:	WARN("Bad time format %lu!\n", wmm->dwMciTimeFormat);    }    /*      TRACE("val=%lu=0x%08lx [tf=%lu] => ret=%lu\n", val, val, wmm->dwMciTimeFormat, ret);    */    return ret;}/************************************************************************** * 			MIDI_ConvertMSToTimeFormat		[internal] */static	DWORD	MIDI_ConvertMSToTimeFormat(WINE_MCIMIDI* wmm, DWORD _val){    DWORD	ret = 0, val = _val;    DWORD	h, m, s, f;    switch (wmm->dwMciTimeFormat) {    case MCI_FORMAT_MILLISECONDS:	ret = val;	break;    case MCI_FORMAT_SMPTE_24:    case MCI_FORMAT_SMPTE_25:    case MCI_FORMAT_SMPTE_30:	h = val / TIME_MS_IN_ONE_HOUR;	m = (val -= h * TIME_MS_IN_ONE_HOUR)   / TIME_MS_IN_ONE_MINUTE;	s = (val -= m * TIME_MS_IN_ONE_MINUTE) / TIME_MS_IN_ONE_SECOND;	switch (wmm->dwMciTimeFormat) {	case MCI_FORMAT_SMPTE_24:	    /* one frame is 1000/24 val long, 1000/24 == 125/3 */	    f = (val * 3) / 125; 	val -= (f * 125) / 3;	    break;	case MCI_FORMAT_SMPTE_25:	    /* one frame is 1000/25 ms long, 1000/25 == 40 */	    f = val / 40; 		val -= f * 40;	    break;	case MCI_FORMAT_SMPTE_30:	    /* one frame is 1000/30 ms long, 1000/30 == 100/3 */	    f = (val * 3) / 100; 	val -= (f * 100) / 3;	    break;	default:	    FIXME("There must be some bad bad programmer\n");	    f = 0;	}	/* val contains the number of ms which cannot make a complete frame */	/* FIXME: is this correct ? programs seem to be happy with that */	ret = (f << 24) | (s << 16) | (m << 8) | (h << 0);	break;    default:	WARN("Bad time format %lu!\n", wmm->dwMciTimeFormat);    }    /*      TRACE("val=%lu [tf=%lu] => ret=%lu=0x%08lx\n", _val, wmm->dwMciTimeFormat, ret, ret);    */    return ret;}/************************************************************************** * 			MIDI_GetMThdLengthMS			[internal] */static	DWORD	MIDI_GetMThdLengthMS(WINE_MCIMIDI* wmm){    WORD	nt;    DWORD	ret = 0;    for (nt = 0; nt < wmm->nTracks; nt++) {	if (wmm->wFormat == 2) {	    ret += wmm->tracks[nt].dwLength;	} else if (wmm->tracks[nt].dwLength > ret) {	    ret = wmm->tracks[nt].dwLength;	}    }    /* FIXME: this is wrong if there is a tempo change inside the file */    return MIDI_ConvertPulseToMS(wmm, ret);}/************************************************************************** * 				MIDI_mciOpen			[internal] */static DWORD MIDI_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpParms){    DWORD		dwRet = 0;    DWORD		dwDeviceID;    WINE_MCIMIDI*	wmm = (WINE_MCIMIDI*)mciGetDriverData(wDevID);    TRACE("(%04x, %08lX, %p)\n", wDevID, dwFlags, lpParms);    if (lpParms == NULL) 	return MCIERR_NULL_PARAMETER_BLOCK;    if (wmm == NULL)		return MCIERR_INVALID_DEVICE_ID;    if (dwFlags & MCI_OPEN_SHAREABLE)	return MCIERR_HARDWARE;    if (wmm->nUseCount > 0) {	/* The driver is already opened on this channel	 * MIDI sequencer cannot be shared	 */

⌨️ 快捷键说明

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