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

📄 midi.c

📁 Wine-20031016
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (!KillTimer(0, midiInTimerID)) {	    WARN("Couldn't stop timer for midi-in\n");	}	midiInTimerID = 0;    }    snd_seq_disconnect_from(midiSeq, port_in, MidiInDev[wDevID].addr.client, MidiInDev[wDevID].addr.port);    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){    TRACE("(%04X);\n", wDevID);    if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;    if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;    MidiInDev[wDevID].state = 1;    MidiInDev[wDevID].startTime = GetTickCount();    return MMSYSERR_NOERROR;}/************************************************************************** *			midStop					[internal] */static DWORD midStop(WORD wDevID){    TRACE("(%04X);\n", wDevID);    if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID;    if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE;    MidiInDev[wDevID].state = 0;    return MMSYSERR_NOERROR;}/************************************************************************** * 				modGetDevCaps			[internal] */static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSA lpCaps, DWORD dwSize){    TRACE("(%04X, %p, %08lX);\n", wDevID, lpCaps, dwSize);    if (wDevID >= MODM_NumDevs)	return MMSYSERR_BADDEVICEID;    if (lpCaps == NULL) 	return MMSYSERR_INVALPARAM;    memcpy(lpCaps, &MidiOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps)));    return MMSYSERR_NOERROR;}/************************************************************************** * 			modOpen					[internal] */static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags){    TRACE("(%04X, %p, %08lX);\n", wDevID, lpDesc, dwFlags);    if (lpDesc == NULL) {	WARN("Invalid Parameter !\n");	return MMSYSERR_INVALPARAM;    }    if (wDevID >= MODM_NumDevs) {	TRACE("MAX_MIDIOUTDRV reached !\n");	return MMSYSERR_BADDEVICEID;    }    if (MidiOutDev[wDevID].midiDesc.hMidi != 0) {	WARN("device already open !\n");	return MMSYSERR_ALLOCATED;    }    if (!MidiOutDev[wDevID].bEnabled) {	WARN("device disabled !\n");	return MIDIERR_NODEVICE;    }    if ((dwFlags & ~CALLBACK_TYPEMASK) != 0) {	WARN("bad dwFlags\n");	return MMSYSERR_INVALFLAG;    }    if (!MidiOutDev[wDevID].bEnabled) {	TRACE("disabled wDevID\n");	return MMSYSERR_NOTENABLED;    }    MidiOutDev[wDevID].lpExtra = 0;    switch (MidiOutDev[wDevID].caps.wTechnology) {    case MOD_FMSYNTH:    case MOD_MIDIPORT:    case MOD_SYNTH:	if (midiOpenSeq(1) < 0) {	    return MMSYSERR_ALLOCATED;	}	break;    default:	WARN("Technology not supported (yet) %d !\n",	     MidiOutDev[wDevID].caps.wTechnology);	return MMSYSERR_NOTENABLED;    }    MidiOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);    MidiOutDev[wDevID].lpQueueHdr = NULL;    MidiOutDev[wDevID].dwTotalPlayed = 0;    MidiOutDev[wDevID].bufsize = 0x3FFF;    MidiOutDev[wDevID].midiDesc = *lpDesc;    /* Connect our app port to the device port */    if (snd_seq_connect_to(midiSeq, port_out, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port) < 0)	return MMSYSERR_NOTENABLED;        if (MIDI_NotifyClient(wDevID, MOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {	WARN("can't notify client !\n");	return MMSYSERR_INVALPARAM;    }    TRACE("Successful !\n");    return MMSYSERR_NOERROR;}/************************************************************************** * 			modClose				[internal] */static DWORD modClose(WORD wDevID){    int	ret = MMSYSERR_NOERROR;    TRACE("(%04X);\n", wDevID);    if (MidiOutDev[wDevID].midiDesc.hMidi == 0) {	WARN("device not opened !\n");	return MMSYSERR_ERROR;    }    /* FIXME: should test that no pending buffer is still in the queue for     * playing */    if (midiSeq == NULL) {	WARN("can't close !\n");	return MMSYSERR_ERROR;    }    switch (MidiOutDev[wDevID].caps.wTechnology) {    case MOD_FMSYNTH:    case MOD_MIDIPORT:        snd_seq_disconnect_to(midiSeq, port_out, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port);	midiCloseSeq();	break;    default:	WARN("Technology not supported (yet) %d !\n",	     MidiOutDev[wDevID].caps.wTechnology);	return MMSYSERR_NOTENABLED;    }    if (MidiOutDev[wDevID].lpExtra != 0) {        HeapFree(GetProcessHeap(), 0, MidiOutDev[wDevID].lpExtra);	MidiOutDev[wDevID].lpExtra = 0;    }     MidiOutDev[wDevID].bufsize = 0;    if (MIDI_NotifyClient(wDevID, MOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {	WARN("can't notify client !\n");	ret = MMSYSERR_INVALPARAM;    }    MidiOutDev[wDevID].midiDesc.hMidi = 0;    return ret;}/************************************************************************** * 			modData					[internal] */static DWORD modData(WORD wDevID, DWORD dwParam){    BYTE	evt = LOBYTE(LOWORD(dwParam));    BYTE	d1  = HIBYTE(LOWORD(dwParam));    BYTE	d2  = LOBYTE(HIWORD(dwParam));        TRACE("(%04X, %08lX);\n", wDevID, dwParam);    if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;    if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;    if (midiSeq == NULL) {	WARN("can't play !\n");	return MIDIERR_NODEVICE;    }    switch (MidiOutDev[wDevID].caps.wTechnology) {    case MOD_SYNTH:    case MOD_MIDIPORT:	{	    int handled = 1; /* Assume event is handled */            snd_seq_event_t event;            snd_seq_ev_clear(&event);	    	    switch (evt & 0xF0) {	    case MIDI_CMD_NOTE_OFF:		snd_seq_ev_set_noteoff(&event, evt&0x0F, d1, d2);		break;	    case MIDI_CMD_NOTE_ON:		snd_seq_ev_set_noteon(&event, evt&0x0F, d1, d2);		break;	    case MIDI_CMD_NOTE_PRESSURE:		snd_seq_ev_set_keypress(&event, evt&0x0F, d1, d2);		break;	    case MIDI_CMD_CONTROL:		snd_seq_ev_set_controller(&event, evt&0x0F, d1, d2);		break;	    case MIDI_CMD_BENDER:		snd_seq_ev_set_pitchbend(&event, evt&0x0F, ((WORD)d1 << 7) | (WORD)d2);		break;	    case MIDI_CMD_PGM_CHANGE:		snd_seq_ev_set_pgmchange(&event, evt&0x0F, d1);		break;	    case MIDI_CMD_CHANNEL_PRESSURE:		snd_seq_ev_set_chanpress(&event, evt&0x0F, d1);		break;	    case MIDI_CMD_COMMON_SYSEX:		switch (evt & 0x0F) {		case 0x00:	/* System Exclusive, don't do it on modData,				 * should require modLongData*/		case 0x01:	/* Undefined */		case 0x04:	/* Undefined. */		case 0x05:	/* Undefined. */		case 0x07:	/* End of Exclusive. */		case 0x09:	/* Undefined. */		case 0x0D:	/* Undefined. */		    handled = 0;		    break;		case 0x06:	/* Tune Request */		case 0x08:	/* Timing Clock. */		case 0x0A:	/* Start. */		case 0x0B:	/* Continue */		case 0x0C:	/* Stop */		case 0x0E: 	/* Active Sensing. */		    /* FIXME: Is this function suitable for these purposes		       (and also Song Select and Song Position Pointer) */	            snd_seq_ev_set_sysex(&event, 1, &evt);		    break;		case 0x0F: 	/* Reset */				/* snd_seq_ev_set_sysex(&event, 1, &evt);				   this other way may be better */		    {			BYTE reset_sysex_seq[] = {MIDI_CMD_COMMON_SYSEX, 0x7e, 0x7f, 0x09, 0x01, 0xf7};			snd_seq_ev_set_sysex(&event, sizeof(reset_sysex_seq), reset_sysex_seq);		    }		    break;		case 0x03:	/* Song Select. */		    {			BYTE buf[2];			buf[0] = evt;			buf[1] = d1;			snd_seq_ev_set_sysex(&event, sizeof(buf), buf);	            }		case 0x02:	/* Song Position Pointer. */		    {			BYTE buf[3];			buf[0] = evt;			buf[1] = d1;			buf[2] = d2;			snd_seq_ev_set_sysex(&event, sizeof(buf), buf);	            }		}		break;	    }	    if (handled)                snd_seq_event_output_direct(midiSeq, &event);	}	break;    default:	WARN("Technology not supported (yet) %d !\n",	     MidiOutDev[wDevID].caps.wTechnology);	return MMSYSERR_NOTENABLED;    }    return MMSYSERR_NOERROR;}/************************************************************************** *		modLongData					[internal] */static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize){    int		len_add = 0;    LPBYTE	lpData, lpNewData = NULL;    snd_seq_event_t event;    TRACE("(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);    /* Note: MS doc does not say much about the dwBytesRecorded member of the MIDIHDR structure     * but it seems to be used only for midi input.     * Taking a look at the WAVEHDR structure (which is quite similar) confirms this assumption.     */

⌨️ 快捷键说明

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