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

📄 mcimidi.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 3 页
字号:
	return MCIERR_DEVICE_OPEN;    }    wmm->nUseCount++;    wmm->hFile = 0;    wmm->hMidi = 0;    dwDeviceID = lpParms->wDeviceID;    TRACE("wDevID=%04X (lpParams->wDeviceID=%08lX)\n", wDevID, dwDeviceID);    /*	lpParms->wDeviceID = wDevID;*/    if (dwFlags & MCI_OPEN_ELEMENT) {	TRACE("MCI_OPEN_ELEMENT '%s' !\n", lpParms->lpstrElementName);	if (lpParms->lpstrElementName && strlen(lpParms->lpstrElementName) > 0) {	    wmm->hFile = mmioOpenA(lpParms->lpstrElementName, NULL,				   MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);	    if (wmm->hFile == 0) {		WARN("Can't find file '%s' !\n", lpParms->lpstrElementName);		wmm->nUseCount--;		return MCIERR_FILE_NOT_FOUND;	    }	} else {	    wmm->hFile = 0;	}    }    TRACE("hFile=%p\n", wmm->hFile);    /* FIXME: should I get a strdup() of it instead? */    wmm->lpstrElementName = HeapAlloc( GetProcessHeap(), 0, strlen(lpParms->lpstrElementName)+1 );    strcpy( wmm->lpstrElementName, lpParms->lpstrElementName );    wmm->lpstrCopyright = NULL;    wmm->lpstrName = NULL;    wmm->wNotifyDeviceID = dwDeviceID;    wmm->dwStatus = MCI_MODE_NOT_READY;	/* while loading file contents */    /* spec says it should be the default format from the MIDI file... */    wmm->dwMciTimeFormat = MCI_FORMAT_MILLISECONDS;    if (wmm->hFile != 0) {	MMCKINFO	ckMainRIFF;	MMCKINFO	mmckInfo;	DWORD		dwOffset = 0;	if (mmioDescend(wmm->hFile, &ckMainRIFF, NULL, 0) != 0) {	    dwRet = MCIERR_INVALID_FILE;	} else {	    TRACE("ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",		  (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType, ckMainRIFF.cksize);	    if (ckMainRIFF.ckid == FOURCC_RIFF && ckMainRIFF.fccType == mmioFOURCC('R', 'M', 'I', 'D')) {		mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');		mmioSeek(wmm->hFile, ckMainRIFF.dwDataOffset + ((ckMainRIFF.cksize + 1) & ~1), SEEK_SET);		if (mmioDescend(wmm->hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) == 0) {		    TRACE("... is a 'RMID' file \n");		    dwOffset = mmckInfo.dwDataOffset;		} else {		    dwRet = MCIERR_INVALID_FILE;		}	    }	    if (dwRet == 0 && MIDI_mciReadMThd(wmm, dwOffset) != 0) {		WARN("Can't read 'MThd' header \n");		dwRet = MCIERR_INVALID_FILE;	    }	}    } else {	TRACE("hFile==0, setting #tracks to 0; is this correct ?\n");	wmm->nTracks = 0;	wmm->wFormat = 0;	wmm->nDivision = 1;    }    if (dwRet != 0) {	wmm->nUseCount--;	if (wmm->hFile != 0)	    mmioClose(wmm->hFile, 0);	wmm->hFile = 0;    } else {	wmm->dwPositionMS = 0;	wmm->dwStatus = MCI_MODE_STOP;    }    return dwRet;}/************************************************************************** * 				MIDI_mciStop			[internal] */static DWORD MIDI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms){    WINE_MCIMIDI*	wmm = MIDI_mciGetOpenDev(wDevID);    DWORD		dwRet = 0;    TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);    if (wmm == NULL)	return MCIERR_INVALID_DEVICE_ID;    if (wmm->dwStatus != MCI_MODE_STOP) {	int	oldstat = wmm->dwStatus;	wmm->dwStatus = MCI_MODE_NOT_READY;	if (oldstat == MCI_MODE_PAUSE)	    dwRet = midiOutReset((HMIDIOUT)wmm->hMidi);	while (wmm->dwStatus != MCI_MODE_STOP)	    Sleep(10);    }    /* sanitiy reset */    wmm->dwStatus = MCI_MODE_STOP;    TRACE("wmm->dwStatus=%d\n", wmm->dwStatus);    if (lpParms && (dwFlags & MCI_NOTIFY)) {	TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),			wmm->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);    }    return 0;}/************************************************************************** * 				MIDI_mciClose			[internal] */static DWORD MIDI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms){    WINE_MCIMIDI*	wmm = MIDI_mciGetOpenDev(wDevID);    TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);    if (wmm == NULL)	return MCIERR_INVALID_DEVICE_ID;    if (wmm->dwStatus != MCI_MODE_STOP) {	MIDI_mciStop(wDevID, MCI_WAIT, lpParms);    }    wmm->nUseCount--;    if (wmm->nUseCount == 0) {	if (wmm->hFile != 0) {	    mmioClose(wmm->hFile, 0);	    wmm->hFile = 0;	    TRACE("hFile closed !\n");	}	HeapFree(GetProcessHeap(), 0, wmm->tracks);	HeapFree(GetProcessHeap(), 0, (LPSTR)wmm->lpstrElementName);	HeapFree(GetProcessHeap(), 0, (LPSTR)wmm->lpstrCopyright);	HeapFree(GetProcessHeap(), 0, (LPSTR)wmm->lpstrName);    } else {	TRACE("Shouldn't happen... nUseCount=%d\n", wmm->nUseCount);	return MCIERR_INTERNAL;    }    if (lpParms && (dwFlags & MCI_NOTIFY)) {	TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);	mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),			wmm->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);    }    return 0;}/************************************************************************** * 				MIDI_mciFindNextEvent		[internal] */static MCI_MIDITRACK*	MIDI_mciFindNextEvent(WINE_MCIMIDI* wmm, LPDWORD hiPulse){    WORD		cnt, nt;    MCI_MIDITRACK*	mmt;    *hiPulse = 0xFFFFFFFFul;    cnt = 0xFFFFu;    for (nt = 0; nt < wmm->nTracks; nt++) {	mmt = &wmm->tracks[nt];	if (mmt->wStatus == 0)	    continue;	if (mmt->dwEventPulse < *hiPulse) {	    *hiPulse = mmt->dwEventPulse;	    cnt = nt;	}    }    return (cnt == 0xFFFFu) ? 0 /* no more event on all tracks */	: &wmm->tracks[cnt];}/************************************************************************** * 				MIDI_mciPlay			[internal] */static DWORD MIDI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms){    DWORD		dwStartMS, dwEndMS;    DWORD		dwRet = 0;    WORD		doPlay, nt;    MCI_MIDITRACK*	mmt;    DWORD		hiPulse;    WINE_MCIMIDI*	wmm = MIDI_mciGetOpenDev(wDevID);    TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);    if (wmm == NULL)	return MCIERR_INVALID_DEVICE_ID;    if (wmm->hFile == 0) {	WARN("Can't play: no file '%s' !\n", wmm->lpstrElementName);	return MCIERR_FILE_NOT_FOUND;    }    if (wmm->dwStatus != MCI_MODE_STOP) {	if (wmm->dwStatus == MCI_MODE_PAUSE) {	    /* FIXME: parameters (start/end) in lpParams may not be used */	    return MIDI_mciResume(wDevID, dwFlags, (LPMCI_GENERIC_PARMS)lpParms);	}	WARN("Can't play: device is not stopped !\n");	return MCIERR_INTERNAL;    }    if (!(dwFlags & MCI_WAIT)) {	/** FIXME: I'm not 100% sure that wNotifyDeviceID is the right value in all cases ??? */	return MCI_SendCommandAsync(wmm->wNotifyDeviceID, MCI_PLAY, dwFlags, (DWORD)lpParms, sizeof(LPMCI_PLAY_PARMS));    }    if (lpParms && (dwFlags & MCI_FROM)) {	dwStartMS = MIDI_ConvertTimeFormatToMS(wmm, lpParms->dwFrom);    } else {	dwStartMS = wmm->dwPositionMS;    }    if (lpParms && (dwFlags & MCI_TO)) {	dwEndMS = MIDI_ConvertTimeFormatToMS(wmm, lpParms->dwTo);    } else {	dwEndMS = 0xFFFFFFFFul;    }    TRACE("Playing from %lu to %lu\n", dwStartMS, dwEndMS);    /* init tracks */    for (nt = 0; nt < wmm->nTracks; nt++) {	mmt = &wmm->tracks[nt];	mmt->wStatus = 1;	/* ok, playing */	mmt->dwIndex = mmt->dwFirst;	if (wmm->wFormat == 2 && nt > 0) {	    mmt->dwEventPulse = wmm->tracks[nt - 1].dwLength;	} else {	    mmt->dwEventPulse = 0;	}	MIDI_mciReadNextEvent(wmm, mmt); /* FIXME == 0 */    }    dwRet = midiOutOpen((LPHMIDIOUT)&wmm->hMidi, MIDIMAPPER, 0L, 0L, CALLBACK_NULL);    /*	dwRet = midiInOpen(&wmm->hMidi, MIDIMAPPER, 0L, 0L, CALLBACK_NULL);*/    if (dwRet != MMSYSERR_NOERROR) {	return dwRet;    }    wmm->dwPulse = 0;    wmm->dwTempo = 500000;    wmm->dwStatus = MCI_MODE_PLAY;    wmm->dwPositionMS = 0;    wmm->wStartedPlaying = FALSE;    while (wmm->dwStatus != MCI_MODE_STOP && wmm->dwStatus != MCI_MODE_NOT_READY) {	/* it seems that in case of multi-threading, gcc is optimizing just a little bit	 * too much. Tell gcc not to optimize status value using volatile.	 */	while (((volatile WINE_MCIMIDI*)wmm)->dwStatus == MCI_MODE_PAUSE);	doPlay = (wmm->dwPositionMS >= dwStartMS && wmm->dwPositionMS <= dwEndMS);	TRACE("wmm->dwStatus=%d, doPlay=%c\n", wmm->dwStatus, doPlay ? 'T' : 'F');	if ((mmt = MIDI_mciFindNextEvent(wmm, &hiPulse)) == NULL)	    break;  /* no more event on tracks */	/* if starting playing, then set StartTicks to the value it would have had	 * if play had started at position 0	 */	if (doPlay && !wmm->wStartedPlaying) {	    wmm->dwStartTicks = GetTickCount() - MIDI_ConvertPulseToMS(wmm, wmm->dwPulse);	    wmm->wStartedPlaying = TRUE;	    TRACE("Setting dwStartTicks to %lu\n", wmm->dwStartTicks);	}	if (hiPulse > wmm->dwPulse) {	    wmm->dwPositionMS += MIDI_ConvertPulseToMS(wmm, hiPulse - wmm->dwPulse);	    if (doPlay) {		DWORD	togo = wmm->dwStartTicks + wmm->dwPositionMS;		DWORD	tc = GetTickCount();		TRACE("Pulses hi=0x%08lx <> cur=0x%08lx\n", hiPulse, wmm->dwPulse);		TRACE("Wait until %lu => %lu ms\n",		      tc - wmm->dwStartTicks, togo - wmm->dwStartTicks);		if (tc < togo)		    Sleep(togo - tc);	    }	    wmm->dwPulse = hiPulse;	}	switch (LOBYTE(LOWORD(mmt->dwEventData))) {	case 0xF0:	case 0xF7:	/* sysex events */	    {		FIXME("Not handling SysEx events (yet)\n");	    }	    break;	case 0xFF:	    /* position after meta data header */	    mmioSeek(wmm->hFile, mmt->dwIndex + HIWORD(mmt->dwEventData), SEEK_SET);	    switch (HIBYTE(LOWORD(mmt->dwEventData))) {	    case 0x00: /* 16-bit sequence number */		if (TRACE_ON(mcimidi)) {		    WORD	twd;		    MIDI_mciReadWord(wmm, &twd);	/* == 0 */		    TRACE("Got sequence number %u\n", twd);		}		break;	    case 0x01: /* any text */	    case 0x02: /* Copyright Message text */	    case 0x03: /* Sequence/Track Name text */	    case 0x04: /* Instrument Name text */	    case 0x05: /* Lyric text */	    case 0x06: /* Marker text */	    case 0x07: /* Cue-point text */		if (TRACE_ON(mcimidi)) {		    char	buf[1024];		    WORD	len = mmt->wEventLength - HIWORD(mmt->dwEventData);		    static const char*	info[8] = {"", "Text", "Copyright", "Seq/Trk name",						   "Instrument", "Lyric", "Marker", "Cue-point"};		    WORD	idx = HIBYTE(LOWORD(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 */			TRACE("%s => \"%s\"\n", (idx < 8 ) ? info[idx] : "", buf);		    } else {			WARN("Couldn't read data for %s\n", (idx < 8) ? info[idx] : "");		    }		}		break;	    case 0x20:		/* MIDI channel (cc) */		if (FIXME_ON(mcimidi)) {		    BYTE	bt;		    MIDI_mciReadByte(wmm, &bt);	/* == 0 */		    FIXME("NIY: MIDI channel=%u, track=%u\n", bt, mmt->wTrackNr);		}		break;	    case 0x21:		/* MIDI port (pp) */		if (FIXME_ON(mcimidi)) {		    BYTE	bt;		    MIDI_mciReadByte(wmm, &bt);	/* == 0 */		    FIXME("NIY: MIDI port=%u, track=%u\n", bt, mmt->wTrackNr);		}		break;	    case 0x2F: /* end of track */		mmt->wStatus = 0;		break;	    case 0x51:/* set tempo */		/* Tempo is expressed in 

⌨️ 快捷键说明

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