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

📄 midi.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 4 页
字号:
 * 			midiCloseSeq				[internal] */static int midiCloseSeq(void){    if (--numOpenMidiSeq == 0) {	close(midiSeqFD);	midiSeqFD = -1;    }    return 0;}/* FIXME: this is a bad idea, it's even not static... */SEQ_DEFINEBUF(1024);/* FIXME: this is not reentrant, not static - because of global variable * _seqbuf and al. *//************************************************************************** * 			seqbuf_dump				[internal] * * Used by SEQ_DUMPBUF to flush the buffer. * */void seqbuf_dump(void){    if (_seqbufptr) {	if (write(midiSeqFD, _seqbuf, _seqbufptr) == -1) {	    WARN("Can't write data to sequencer %d, errno %d (%s)!\n",		 midiSeqFD, errno, strerror(errno));	}	/* FIXME:	 *	in any case buffer is lost so that if many errors occur the buffer	 * will not overrun	 */	_seqbufptr = 0;    }}/************************************************************************** * 			midReceiveChar				[internal] */static void midReceiveChar(WORD wDevID, unsigned char value, DWORD dwTime){    DWORD		toSend = 0;    TRACE("Adding %02xh to %d[%d]\n", value, wDevID, MidiInDev[wDevID].incLen);    if (wDevID >= MIDM_NumDevs) {	WARN("bad devID\n");	return;    }    if (MidiInDev[wDevID].state <= 0) {	TRACE("disabled or input not started, thrown away\n");	return;    }    if (MidiInDev[wDevID].state & 2) { /* system exclusive */	LPMIDIHDR	lpMidiHdr = MidiInDev[wDevID].lpQueueHdr;	WORD 		sbfb = FALSE;	if (lpMidiHdr) {	    LPBYTE	lpData = lpMidiHdr->lpData;	    lpData[lpMidiHdr->dwBytesRecorded++] = value;	    if (lpMidiHdr->dwBytesRecorded == lpMidiHdr->dwBufferLength) {		sbfb = TRUE;	    }	}	if (value == 0xF7) { /* then end */	    MidiInDev[wDevID].state &= ~2;	    sbfb = TRUE;	}	if (sbfb && lpMidiHdr != NULL) {	    lpMidiHdr = MidiInDev[wDevID].lpQueueHdr;	    lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;	    lpMidiHdr->dwFlags |= MHDR_DONE;	    MidiInDev[wDevID].lpQueueHdr = (LPMIDIHDR)lpMidiHdr->lpNext;	    if (MIDI_NotifyClient(wDevID, MIM_LONGDATA, (DWORD)lpMidiHdr, dwTime) != MMSYSERR_NOERROR) {		WARN("Couldn't notify client\n");	    }	}	return;    }#define IS_CMD(_x)	(((_x) & 0x80) == 0x80)#define IS_SYS_CMD(_x)	(((_x) & 0xF0) == 0xF0)    if (!IS_CMD(value) && MidiInDev[wDevID].incLen == 0) { /* try to reuse old cmd */	if (IS_CMD(MidiInDev[wDevID].incPrev) && !IS_SYS_CMD(MidiInDev[wDevID].incPrev)) {	    MidiInDev[wDevID].incoming[0] = MidiInDev[wDevID].incPrev;	    MidiInDev[wDevID].incLen = 1;	    TRACE("Reusing old command %02xh\n", MidiInDev[wDevID].incPrev);	} else {	    FIXME("error for midi-in, should generate MIM_ERROR notification:"		  " prev=%02Xh, incLen=%02Xh\n",		  MidiInDev[wDevID].incPrev, MidiInDev[wDevID].incLen);	    return;	}    }    MidiInDev[wDevID].incoming[(int)(MidiInDev[wDevID].incLen++)] = value;    if (MidiInDev[wDevID].incLen == 1 && !IS_SYS_CMD(MidiInDev[wDevID].incoming[0])) {	/* store new cmd, just in case */	MidiInDev[wDevID].incPrev = MidiInDev[wDevID].incoming[0];    }#undef IS_CMD#undef IS_SYS_CMD    switch (MidiInDev[wDevID].incoming[0] & 0xF0) {    case MIDI_NOTEOFF:    case MIDI_NOTEON:    case MIDI_KEY_PRESSURE:    case MIDI_CTL_CHANGE:    case MIDI_PITCH_BEND:	if (MidiInDev[wDevID].incLen == 3) {	    toSend = (MidiInDev[wDevID].incoming[2] << 16) |		(MidiInDev[wDevID].incoming[1] <<  8) |		(MidiInDev[wDevID].incoming[0] <<  0);	}	break;    case MIDI_PGM_CHANGE:    case MIDI_CHN_PRESSURE:	if (MidiInDev[wDevID].incLen == 2) {	    toSend = (MidiInDev[wDevID].incoming[1] <<  8) |		(MidiInDev[wDevID].incoming[0] <<  0);	}	break;    case MIDI_SYSTEM_PREFIX:	if (MidiInDev[wDevID].incoming[0] == 0xF0) {	    MidiInDev[wDevID].state |= 2;	    MidiInDev[wDevID].incLen = 0;	} else {	    if (MidiInDev[wDevID].incLen == 1) {		toSend = (MidiInDev[wDevID].incoming[0] <<  0);	    }	}	break;    default:	WARN("This shouldn't happen (%02X)\n", MidiInDev[wDevID].incoming[0]);    }    if (toSend != 0) {	TRACE("Sending event %08lx\n", toSend);	MidiInDev[wDevID].incLen =	0;	dwTime -= MidiInDev[wDevID].startTime;	if (MIDI_NotifyClient(wDevID, MIM_DATA, toSend, dwTime) != MMSYSERR_NOERROR) {	    WARN("Couldn't notify client\n");	}    }}static VOID WINAPI midTimeCallback(HWND hwnd, UINT msg, UINT id, DWORD dwTime){    unsigned char buffer[256];    int len, idx;        TRACE("(%p, %d, %d, %lu)\n", hwnd, msg, id, dwTime);    len = read(midiSeqFD, buffer, sizeof(buffer));    if (len < 0) return;    if ((len % 4) != 0) {	WARN("Bad length %d, errno %d (%s)\n", len, errno, strerror(errno));	return;    }    for (idx = 0; idx < len; ) {	if (buffer[idx] & 0x80) {	    TRACE(		  "Reading<8> %02x %02x %02x %02x %02x %02x %02x %02x\n",		  buffer[idx + 0], buffer[idx + 1],		  buffer[idx + 2], buffer[idx + 3],		  buffer[idx + 4], buffer[idx + 5],		  buffer[idx + 6], buffer[idx + 7]);	    idx += 8;	} else {	    switch (buffer[idx + 0]) {	    case SEQ_WAIT:	    case SEQ_ECHO:		break;	    case SEQ_MIDIPUTC:		midReceiveChar(buffer[idx + 2], buffer[idx + 1], dwTime);		break;	    default:		TRACE("Unsupported event %d\n", buffer[idx + 0]);		break;	    }	    idx += 4;	}    }}/************************************************************************** * 				midGetDevCaps			[internal] */static DWORD midGetDevCaps(WORD wDevID, LPMIDIINCAPSA lpCaps, DWORD dwSize){    TRACE("(%04X, %p, %08lX);\n", wDevID, lpCaps, dwSize);    if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;    if (lpCaps == NULL)		return MMSYSERR_INVALPARAM;    memcpy(lpCaps, &MidiInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));    return MMSYSERR_NOERROR;}/************************************************************************** * 			midOpen					[internal] */static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags){    TRACE("(%04X, %p, %08lX);\n", wDevID, lpDesc, dwFlags);    if (lpDesc == NULL) {	WARN("Invalid Parameter !\n");	return MMSYSERR_INVALPARAM;    }    /* FIXME :     *	how to check that content of lpDesc is correct ?     */    if (wDevID >= MIDM_NumDevs) {	WARN("wDevID too large (%u) !\n", wDevID);	return MMSYSERR_BADDEVICEID;    }    if (MidiInDev[wDevID].state == -1) {                WARN("device disabled\n");        return MIDIERR_NODEVICE;    }    if (MidiInDev[wDevID].midiDesc.hMidi != 0) {	WARN("device already open !\n");	return MMSYSERR_ALLOCATED;    }    if ((dwFlags & MIDI_IO_STATUS) != 0) {	WARN("No support for MIDI_IO_STATUS in dwFlags yet, ignoring it\n");	dwFlags &= ~MIDI_IO_STATUS;    }    if ((dwFlags & ~CALLBACK_TYPEMASK) != 0) {	FIXME("Bad dwFlags\n");	return MMSYSERR_INVALFLAG;    }    if (midiOpenSeq() < 0) {	return MMSYSERR_ERROR;    }    if (numStartedMidiIn++ == 0) {	midiInTimerID = SetTimer(0, 0, 250, midTimeCallback);	if (!midiInTimerID) {	    numStartedMidiIn = 0;	    WARN("Couldn't start timer for midi-in\n");	    midiCloseSeq();	    return MMSYSERR_ERROR;	}	TRACE("Starting timer (%u) for midi-in\n", midiInTimerID);    }    MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);    MidiInDev[wDevID].lpQueueHdr = NULL;    MidiInDev[wDevID].dwTotalPlayed = 0;    MidiInDev[wDevID].bufsize = 0x3FFF;    MidiInDev[wDevID].midiDesc = *lpDesc;    MidiInDev[wDevID].state = 0;    MidiInDev[wDevID].incLen = 0;    MidiInDev[wDevID].startTime = 0;    if (MIDI_NotifyClient(wDevID, MIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {	WARN("can't notify client !\n");	return MMSYSERR_INVALPARAM;    }    return MMSYSERR_NOERROR;}/************************************************************************** * 			midClose				[internal] */static DWORD midClose(WORD wDevID){    int		ret = MMSYSERR_NOERROR;    TRACE("(%04X);\n", wDevID);    if (wDevID >= MIDM_NumDevs) {	WARN("wDevID too big (%u) !\n", wDevID);	return MMSYSERR_BADDEVICEID;    }    if (MidiInDev[wDevID].midiDesc.hMidi == 0) {	WARN("device not opened !\n");	return MMSYSERR_ERROR;    }    if (MidiInDev[wDevID].lpQueueHdr != 0) {	return MIDIERR_STILLPLAYING;    }    if (midiSeqFD == -1) {	WARN("ooops !\n");	return MMSYSERR_ERROR;    }    if (--numStartedMidiIn == 0) {	TRACE("Stopping timer for midi-in\n");	if (!KillTimer(0, midiInTimerID)) {	    WARN("Couldn't stop timer for midi-in\n");	}	midiInTimerID = 0;    }    midiCloseSeq();    MidiInDev[wDevID].bufsize = 0;    if (MIDI_NotifyClient(wDevID, MIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {	WARN("can't notify client !\n");	ret = MMSYSERR_INVALPARAM;    }    MidiInDev[wDevID].midiDesc.hMidi = 0;    return ret;}/************************************************************************** * 				midAddBuffer			[internal] */static DWORD midAddBuffer(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize){    TRACE("(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);    if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;    if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;    if (lpMidiHdr == NULL)	return MMSYSERR_INVALPARAM;    if (sizeof(MIDIHDR) > dwSize) return MMSYSERR_INVALPARAM;    if (lpMidiHdr->dwBufferLength == 0) return MMSYSERR_INVALPARAM;    if (lpMidiHdr->dwFlags & MHDR_INQUEUE) return MIDIERR_STILLPLAYING;    if (!(lpMidiHdr->dwFlags & MHDR_PREPARED)) return MIDIERR_UNPREPARED;    if (MidiInDev[wDevID].lpQueueHdr == 0) {	MidiInDev[wDevID].lpQueueHdr = lpMidiHdr;    } else {	LPMIDIHDR	ptr;	for (ptr = MidiInDev[wDevID].lpQueueHdr;	     ptr->lpNext != 0;	     ptr = (LPMIDIHDR)ptr->lpNext);	ptr->lpNext = (struct midihdr_tag*)lpMidiHdr;    }    return MMSYSERR_NOERROR;}/************************************************************************** * 				midPrepare			[internal] */static DWORD midPrepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize){    TRACE("(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);    if (dwSize < sizeof(MIDIHDR) || lpMidiHdr == 0 ||	lpMidiHdr->lpData == 0 || lpMidiHdr->dwFlags != 0 ||	lpMidiHdr->dwBufferLength >= 0x10000ul)	return MMSYSERR_INVALPARAM;    lpMidiHdr->lpNext = 0;    lpMidiHdr->dwFlags |= MHDR_PREPARED;    lpMidiHdr->dwBytesRecorded = 0;    return MMSYSERR_NOERROR;}/************************************************************************** * 				midUnprepare			[internal] */static DWORD midUnprepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize){    TRACE("(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);    if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;    if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;    if (dwSize < sizeof(MIDIHDR) || lpMidiHdr == 0 ||	lpMidiHdr->lpData == 0 || lpMidiHdr->dwBufferLength >= 0x10000ul)	return MMSYSERR_INVALPARAM;    if (!(lpMidiHdr->dwFlags & MHDR_PREPARED)) return MIDIERR_UNPREPARED;    if (lpMidiHdr->dwFlags & MHDR_INQUEUE) return MIDIERR_STILLPLAYING;    lpMidiHdr->dwFlags &= ~MHDR_PREPARED;    return MMSYSERR_NOERROR;}/************************************************************************** * 			midReset				[internal] */static DWORD midReset(WORD wDevID){    DWORD		dwTime = GetTickCount();    TRACE("(%04X);\n", wDevID);    if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;    if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;    while (MidiInDev[wDevID].lpQueueHdr) {	MidiInDev[wDevID].lpQueueHdr->dwFlags &= ~MHDR_INQUEUE;	MidiInDev[wDevID].lpQueueHdr->dwFlags |= MHDR_DONE;	/* FIXME: when called from 16 bit, lpQueueHdr needs to be a segmented ptr */	if (MIDI_NotifyClient(wDevID, MIM_LONGDATA,			      (DWORD)MidiInDev[wDevID].lpQueueHdr, dwTime) != MMSYSERR_NOERROR) {	    WARN("Couldn't notify client\n");	}	MidiInDev[wDevID].lpQueueHdr = (LPMIDIHDR)MidiInDev[wDevID].lpQueueHdr->lpNext;    }    return MMSYSERR_NOERROR;}/************************************************************************** * 			midStart				[internal] */static DWORD midStart(WORD wDevID){

⌨️ 快捷键说明

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