this patch fixes some issues while handling several midi devices on the same device basically, it doesn't abort the device discovery when an error occurs, but just mark the device as disabled and moved on to the next one A+
Name: oss_midi ChangeLog: better support for multiple midi devices on the OSS interface License: X11 GenDate: 2002/11/19 19:57:51 UTC ModifiedFiles: dlls/winmm/wineoss/midi.c AddedFiles: =================================================================== RCS file: /home/cvs/cvsroot/wine/wine/dlls/winmm/wineoss/midi.c,v retrieving revision 1.29 diff -u -u -r1.29 midi.c --- dlls/winmm/wineoss/midi.c 18 Oct 2002 23:48:57 -0000 1.29 +++ dlls/winmm/wineoss/midi.c 17 Nov 2002 10:45:21 -0000 @@ -29,6 +29,7 @@ #include "config.h" #include <string.h> +#include <stdio.h> #ifdef HAVE_UNISTD_H # include <unistd.h> #endif @@ -52,7 +53,7 @@ #define MIDI_SEQ "/dev/sequencer" typedef struct { - int state; + int state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */ DWORD bufsize; MIDIOPENDESC midiDesc; WORD wFlags; @@ -62,54 +63,37 @@ unsigned char incPrev; char incLen; DWORD startTime; + MIDIINCAPSA caps; } WINE_MIDIIN; typedef struct { - int state; + BOOL bEnabled; DWORD bufsize; MIDIOPENDESC midiDesc; WORD wFlags; LPMIDIHDR lpQueueHdr; DWORD dwTotalPlayed; void* lpExtra; /* according to port type (MIDI, FM...), extra data when needed */ + MIDIOUTCAPSA caps; } WINE_MIDIOUT; static WINE_MIDIIN MidiInDev [MAX_MIDIINDRV ]; static WINE_MIDIOUT MidiOutDev[MAX_MIDIOUTDRV]; -/* this is the total number of MIDI out devices found */ -static int MODM_NUMDEVS = 0; -/* this is the number of FM synthetizers (index from 0 to - NUMFMSYNTHDEVS - 1) */ -static int MODM_NUMFMSYNTHDEVS = 0; -/* this is the number of Midi ports (index from NUMFMSYNTHDEVS to - NUMFMSYNTHDEVS + NUMMIDIDEVS - 1) */ -static int MODM_NUMMIDIDEVS = 0; +/* this is the total number of MIDI out devices found (synth and port) */ +static int MODM_NumDevs = 0; +/* this is the number of FM synthetizers (index from 0 to NUMFMSYNTHDEVS - 1) */ +static int MODM_NumFMSynthDevs = 0; +/* the Midi ports have index from NUMFMSYNTHDEVS to NumDevs - 1 */ /* this is the total number of MIDI out devices found */ -static int MIDM_NUMDEVS = 0; +static int MIDM_NumDevs = 0; static int midiSeqFD = -1; static int numOpenMidiSeq = 0; static UINT midiInTimerID = 0; static int numStartedMidiIn = 0; -/* this structure holds pointers with information for each MIDI - * out device found. - */ -static LPMIDIOUTCAPSA midiOutDevices[MAX_MIDIOUTDRV]; - -/* this structure holds pointers with information for each MIDI - * in device found. - */ -static LPMIDIINCAPSA midiInDevices [MAX_MIDIINDRV]; - -/* - * FIXME : all tests on device ID for midXXX and modYYY are made against - * MAX_MIDIxxDRV (when they are made) but should be done against the actual - * number of midi devices found... - */ - /*======================================================================* * Low level MIDI implementation * *======================================================================*/ @@ -186,51 +170,51 @@ } for (i = 0; i < numsynthdevs; i++) { - LPMIDIOUTCAPSA tmplpCaps; - - sinfo.device = i; - status = ioctl(midiSeqFD, SNDCTL_SYNTH_INFO, &sinfo); - if (status == -1) { - ERR("ioctl for synth info failed.\n"); - midiCloseSeq(); - return TRUE; - } - - tmplpCaps = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIOUTCAPSA)); - if (!tmplpCaps) - break; - /* We also have the information sinfo.synth_subtype, not used here - */ - /* Manufac ID. We do not have access to this with soundcard.h * Does not seem to be a problem, because in mmsystem.h only * Microsoft's ID is listed. */ - tmplpCaps->wMid = 0x00FF; - tmplpCaps->wPid = 0x0001; /* FIXME Product ID */ + MidiOutDev[i].caps.wMid = 0x00FF; + MidiOutDev[i].caps.wPid = 0x0001; /* FIXME Product ID */ /* Product Version. We simply say "1" */ - tmplpCaps->vDriverVersion = 0x001; - strcpy(tmplpCaps->szPname, sinfo.name); - - tmplpCaps->wTechnology = MIDI_UnixToWindowsDeviceType(sinfo.synth_type); - tmplpCaps->wVoices = sinfo.nr_voices; - - /* FIXME Is it possible to know the maximum - * number of simultaneous notes of a soundcard ? - * I believe we don't have this information, but - * it's probably equal or more than wVoices - */ - tmplpCaps->wNotes = sinfo.nr_voices; - tmplpCaps->wChannelMask= 0xFFFF; + MidiOutDev[i].caps.vDriverVersion = 0x001; + MidiOutDev[i].caps.wChannelMask = 0xFFFF; /* FIXME Do we have this information? * Assuming the soundcards can handle * MIDICAPS_VOLUME and MIDICAPS_LRVOLUME but * not MIDICAPS_CACHE. */ - tmplpCaps->dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME; + MidiOutDev[i].caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME; + + sinfo.device = i; + status = ioctl(midiSeqFD, SNDCTL_SYNTH_INFO, &sinfo); + if (status == -1) { + ERR("ioctl for synth info failed on %d, disabling it.\n", i); + + sprintf(MidiOutDev[i].caps.szPname, "Wine OSS Midi Out (#%d) - disabled", i); + + MidiOutDev[i].caps.wTechnology = MOD_MIDIPORT; + MidiOutDev[i].caps.wVoices = 16; + MidiOutDev[i].caps.wNotes = 16; + MidiOutDev[i].bEnabled = FALSE; + } else { + strcpy(MidiOutDev[i].caps.szPname, sinfo.name); + + MidiOutDev[i].caps.wTechnology = MIDI_UnixToWindowsDeviceType(sinfo.synth_type); + MidiOutDev[i].caps.wVoices = sinfo.nr_voices; - midiOutDevices[i] = tmplpCaps; + /* FIXME Is it possible to know the maximum + * number of simultaneous notes of a soundcard ? + * I believe we don't have this information, but + * it's probably equal or more than wVoices + */ + MidiOutDev[i].caps.wNotes = sinfo.nr_voices; + MidiOutDev[i].bEnabled = TRUE; + } + + /* We also have the information sinfo.synth_subtype, not used here + */ if (sinfo.capabilities & SYNTH_CAP_INPUT) { FIXME("Synthesizer support MIDI in. Not supported yet (please report)\n"); @@ -238,8 +222,9 @@ TRACE("SynthOut[%d]\tname='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%ld\n" "\tOSS info: synth subtype=%d capa=%lx\n", - i, tmplpCaps->szPname, tmplpCaps->wTechnology, tmplpCaps->wVoices, - tmplpCaps->wNotes, tmplpCaps->wChannelMask, tmplpCaps->dwSupport, + i, MidiOutDev[i].caps.szPname, MidiOutDev[i].caps.wTechnology, + MidiOutDev[i].caps.wVoices, MidiOutDev[i].caps.wNotes, + MidiOutDev[i].caps.wChannelMask, MidiOutDev[i].caps.dwSupport, sinfo.synth_subtype, (long)sinfo.capabilities); } @@ -247,8 +232,8 @@ status = ioctl(midiSeqFD, SNDCTL_SEQ_NRMIDIS, &nummididevs); if (status == -1) { ERR("ioctl on nr midi failed.\n"); - midiCloseSeq(); - return TRUE; + nummididevs = 0; + goto wrapup; } /* FIXME: the two restrictions below could be loosen in some cases */ @@ -265,20 +250,10 @@ } for (i = 0; i < nummididevs; i++) { - LPMIDIOUTCAPSA tmplpOutCaps; - LPMIDIINCAPSA tmplpInCaps; - minfo.device = i; status = ioctl(midiSeqFD, SNDCTL_MIDI_INFO, &minfo); - if (status == -1) { - ERR("ioctl on midi info for device %d failed.\n", i); - midiCloseSeq(); - return TRUE; - } + if (status == -1) WARN("ioctl on midi info for device %d failed.\n", i); - tmplpOutCaps = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIOUTCAPSA)); - if (!tmplpOutCaps) - break; /* This whole part is somewhat obscure to me. I'll keep trying to dig info about it. If you happen to know, please tell us. The very descritive minfo.dev_type was not used here. @@ -286,27 +261,27 @@ /* Manufac ID. We do not have access to this with soundcard.h Does not seem to be a problem, because in mmsystem.h only Microsoft's ID is listed */ - tmplpOutCaps->wMid = 0x00FF; - tmplpOutCaps->wPid = 0x0001; /* FIXME Product ID */ + MidiOutDev[numsynthdevs + i].caps.wMid = 0x00FF; + MidiOutDev[numsynthdevs + i].caps.wPid = 0x0001; /* FIXME Product ID */ /* Product Version. We simply say "1" */ - tmplpOutCaps->vDriverVersion = 0x001; - strcpy(tmplpOutCaps->szPname, minfo.name); - - tmplpOutCaps->wTechnology = MOD_MIDIPORT; /* FIXME Is this right? */ + MidiOutDev[numsynthdevs + i].caps.vDriverVersion = 0x001; + if (status == -1) { + sprintf(MidiOutDev[numsynthdevs + i].caps.szPname, "Wine OSS Midi Out (#%d) - disabled", numsynthdevs + i); + MidiOutDev[numsynthdevs + i].bEnabled = FALSE; + } else { + strcpy(MidiOutDev[numsynthdevs + i].caps.szPname, minfo.name); + MidiOutDev[numsynthdevs + i].bEnabled = TRUE; + } + MidiOutDev[numsynthdevs + i].caps.wTechnology = MOD_MIDIPORT; /* FIXME Is this right? */ /* Does it make any difference? */ - tmplpOutCaps->wVoices = 16; + MidiOutDev[numsynthdevs + i].caps.wVoices = 16; /* Does it make any difference? */ - tmplpOutCaps->wNotes = 16; - tmplpOutCaps->wChannelMask= 0xFFFF; + MidiOutDev[numsynthdevs + i].caps.wNotes = 16; + MidiOutDev[numsynthdevs + i].caps.wChannelMask= 0xFFFF; /* FIXME Does it make any difference? */ - tmplpOutCaps->dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME; - - midiOutDevices[numsynthdevs + i] = tmplpOutCaps; + MidiOutDev[numsynthdevs + i].caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME; - tmplpInCaps = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIINCAPSA)); - if (!tmplpInCaps) - break; /* This whole part is somewhat obscure to me. I'll keep trying to dig info about it. If you happen to know, please tell us. The very descritive minfo.dev_type was not used here. @@ -314,33 +289,36 @@ /* Manufac ID. We do not have access to this with soundcard.h Does not seem to be a problem, because in mmsystem.h only Microsoft's ID is listed */ - tmplpInCaps->wMid = 0x00FF; - tmplpInCaps->wPid = 0x0001; /* FIXME Product ID */ + MidiInDev[i].caps.wMid = 0x00FF; + MidiInDev[i].caps.wPid = 0x0001; /* FIXME Product ID */ /* Product Version. We simply say "1" */ - tmplpInCaps->vDriverVersion = 0x001; - strcpy(tmplpInCaps->szPname, minfo.name); - + MidiInDev[i].caps.vDriverVersion = 0x001; + if (status == -1) { + sprintf(MidiInDev[i].caps.szPname, "Wine OSS Midi In (#%d) - disabled", numsynthdevs + i); + MidiInDev[i].state = -1; + } else { + strcpy(MidiInDev[i].caps.szPname, minfo.name); + MidiInDev[i].state = 0; + } /* FIXME : could we get better information than that ? */ - tmplpInCaps->dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME; - - midiInDevices[i] = tmplpInCaps; + MidiInDev[i].caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME; TRACE("MidiOut[%d]\tname='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%ld\n" "MidiIn [%d]\tname='%s' support=%ld\n" "\tOSS info: midi dev-type=%d, capa=%lx\n", - i, tmplpOutCaps->szPname, tmplpOutCaps->wTechnology, - tmplpOutCaps->wVoices, tmplpOutCaps->wNotes, - tmplpOutCaps->wChannelMask, tmplpOutCaps->dwSupport, - i, tmplpInCaps->szPname, tmplpInCaps->dwSupport, + i, MidiOutDev[numsynthdevs + i].caps.szPname, MidiOutDev[numsynthdevs + i].caps.wTechnology, + MidiOutDev[numsynthdevs + i].caps.wVoices, MidiOutDev[numsynthdevs + i].caps.wNotes, + MidiOutDev[numsynthdevs + i].caps.wChannelMask, MidiOutDev[numsynthdevs + i].caps.dwSupport, + i, MidiInDev[i].caps.szPname, MidiInDev[i].caps.dwSupport, minfo.dev_type, (long)minfo.capabilities); } + wrapup: /* windows does not seem to differentiate Synth from MIDI devices */ - MODM_NUMFMSYNTHDEVS = numsynthdevs; - MODM_NUMMIDIDEVS = nummididevs; - MODM_NUMDEVS = numsynthdevs + nummididevs; + MODM_NumFMSynthDevs = numsynthdevs; + MODM_NumDevs = numsynthdevs + nummididevs; - MIDM_NUMDEVS = nummididevs; + MIDM_NumDevs = nummididevs; /* close file and exit */ midiCloseSeq(); @@ -366,8 +344,8 @@ case MOM_OPEN: case MOM_CLOSE: case MOM_DONE: - if (wDevID > MAX_MIDIOUTDRV) - return MCIERR_INTERNAL; + if (wDevID > MODM_NumDevs) + return MMSYSERR_BADDEVICEID; dwCallBack = MidiOutDev[wDevID].midiDesc.dwCallback; uFlags = MidiOutDev[wDevID].wFlags; @@ -379,8 +357,8 @@ case MIM_CLOSE: case MIM_DATA: case MIM_ERROR: - if (wDevID > MAX_MIDIINDRV) - return MCIERR_INTERNAL; + if (wDevID > MIDM_NumDevs) + return MMSYSERR_BADDEVICEID; dwCallBack = MidiInDev[wDevID].midiDesc.dwCallback; uFlags = MidiInDev[wDevID].wFlags; @@ -389,11 +367,11 @@ break; default: WARN("Unsupported MSW-MIDI message %u\n", wMsg); - return MCIERR_INTERNAL; + return MMSYSERR_ERROR; } return DriverCallback(dwCallBack, uFlags, hDev, wMsg, dwInstance, dwParam1, dwParam2) ? - 0 : MCIERR_INTERNAL; + 0 : MMSYSERR_ERROR; } static int midi_warn = 1; @@ -476,12 +454,12 @@ TRACE("Adding %02xh to %d[%d]\n", value, wDevID, MidiInDev[wDevID].incLen); - if (wDevID >= MAX_MIDIINDRV) { + if (wDevID >= MIDM_NumDevs) { WARN("bad devID\n"); return; } - if (MidiInDev[wDevID].state == 0) { - TRACE("input not started, thrown away\n"); + if (MidiInDev[wDevID].state <= 0) { + TRACE("disabled or input not started, thrown away\n"); return; } @@ -627,10 +605,10 @@ { TRACE("(%04X, %p, %08lX);\n", wDevID, lpCaps, dwSize); - if (wDevID >= MIDM_NUMDEVS) return MMSYSERR_BADDEVICEID; + if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID; if (lpCaps == NULL) return MMSYSERR_INVALPARAM; - memcpy(lpCaps, midiInDevices[wDevID], min(dwSize, sizeof(*lpCaps))); + memcpy(lpCaps, &MidiInDev[wDevID].caps, min(dwSize, sizeof(*lpCaps))); return MMSYSERR_NOERROR; } @@ -650,10 +628,14 @@ /* FIXME : * how to check that content of lpDesc is correct ? */ - if (wDevID >= MAX_MIDIINDRV) { + 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; @@ -708,7 +690,7 @@ TRACE("(%04X);\n", wDevID); - if (wDevID >= MAX_MIDIINDRV) { + if (wDevID >= MIDM_NumDevs) { WARN("wDevID too big (%u) !\n", wDevID); return MMSYSERR_BADDEVICEID; } @@ -749,6 +731,9 @@ { 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; @@ -794,6 +779,9 @@ { 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; @@ -815,6 +803,9 @@ 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; @@ -837,7 +828,8 @@ { TRACE("(%04X);\n", wDevID); - /* FIXME : should test value of wDevID */ + if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID; + if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE; MidiInDev[wDevID].state = 1; MidiInDev[wDevID].startTime = GetTickCount(); @@ -851,7 +843,9 @@ { TRACE("(%04X);\n", wDevID); - /* FIXME : should test value of wDevID */ + if (wDevID >= MIDM_NumDevs) return MMSYSERR_BADDEVICEID; + if (MidiInDev[wDevID].state == -1) return MIDIERR_NODEVICE; + MidiInDev[wDevID].state = 0; return MMSYSERR_NOERROR; } @@ -942,7 +936,7 @@ sChannel* channel = extra->channel; int i; - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].status != sVS_UNUSED) { SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64); } @@ -977,10 +971,10 @@ { TRACE("(%04X, %p, %08lX);\n", wDevID, lpCaps, dwSize); - if (wDevID >= MODM_NUMDEVS) return MMSYSERR_BADDEVICEID; + if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID; if (lpCaps == NULL) return MMSYSERR_INVALPARAM; - memcpy(lpCaps, midiOutDevices[wDevID], min(dwSize, sizeof(*lpCaps))); + memcpy(lpCaps, &MidiOutDev[wDevID].caps, min(dwSize, sizeof(*lpCaps))); return MMSYSERR_NOERROR; } @@ -995,7 +989,7 @@ WARN("Invalid Parameter !\n"); return MMSYSERR_INVALPARAM; } - if (wDevID >= MAX_MIDIOUTDRV) { + if (wDevID >= MODM_NumDevs) { TRACE("MAX_MIDIOUTDRV reached !\n"); return MMSYSERR_BADDEVICEID; } @@ -1003,23 +997,29 @@ 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 (midiOutDevices[wDevID] == NULL) { - TRACE("un-allocated wDevID\n"); - return MMSYSERR_BADDEVICEID; + if (!MidiOutDev[wDevID].bEnabled) { + TRACE("disabled wDevID\n"); + return MMSYSERR_NOTENABLED; } MidiOutDev[wDevID].lpExtra = 0; - switch (midiOutDevices[wDevID]->wTechnology) { + switch (MidiOutDev[wDevID].caps.wTechnology) { case MOD_FMSYNTH: { - void* extra = HeapAlloc(GetProcessHeap(), 0, - sizeof(struct sFMextra) + - sizeof(struct sVoice) * (midiOutDevices[wDevID]->wVoices - 1)); + void* extra; + + extra = HeapAlloc(GetProcessHeap(), 0, + sizeof(struct sFMextra) + + sizeof(struct sVoice) * (MidiOutDev[wDevID].caps.wVoices - 1)); if (extra == 0) { WARN("can't alloc extra data !\n"); @@ -1047,7 +1047,7 @@ break; default: WARN("Technology not supported (yet) %d !\n", - midiOutDevices[wDevID]->wTechnology); + MidiOutDev[wDevID].caps.wTechnology); return MMSYSERR_NOTENABLED; } @@ -1088,14 +1088,14 @@ return MMSYSERR_ERROR; } - switch (midiOutDevices[wDevID]->wTechnology) { + switch (MidiOutDev[wDevID].caps.wTechnology) { case MOD_FMSYNTH: case MOD_MIDIPORT: midiCloseSeq(); break; default: WARN("Technology not supported (yet) %d !\n", - midiOutDevices[wDevID]->wTechnology); + MidiOutDev[wDevID].caps.wTechnology); return MMSYSERR_NOTENABLED; } @@ -1124,11 +1124,14 @@ TRACE("(%04X, %08lX);\n", wDevID, dwParam); + if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID; + if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE; + if (midiSeqFD == -1) { WARN("can't play !\n"); return MIDIERR_NODEVICE; } - switch (midiOutDevices[wDevID]->wTechnology) { + switch (MidiOutDev[wDevID].caps.wTechnology) { case MOD_FMSYNTH: /* FIXME: * - chorus depth controller is not used @@ -1142,7 +1145,7 @@ switch (evt & 0xF0) { case MIDI_NOTEOFF: - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { /* don't stop sustained notes */ if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1) { voice[i].status = sVS_UNUSED; @@ -1152,7 +1155,7 @@ break; case MIDI_NOTEON: if (d2 == 0) { /* note off if velocity == 0 */ - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { /* don't stop sustained notes */ if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1) { voice[i].status = sVS_UNUSED; @@ -1166,7 +1169,7 @@ * - if replaying the same note on the same channel * - the older voice (LRU) */ - for (i = nv = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = nv = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].status == sVS_UNUSED || (voice[i].note == d1 && voice[i].channel == chn)) { nv = i; @@ -1203,7 +1206,7 @@ voice[nv].cntMark = extra->counter++; break; case MIDI_KEY_PRESSURE: - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].status != sVS_UNUSED && voice[i].channel == chn && voice[i].note == d1) { SEQ_KEY_PRESSURE(wDevID, i, d1, d2); } @@ -1217,13 +1220,13 @@ case CTL_EXPRESSION: channel[chn].expression = d2; break; case CTL_SUSTAIN: channel[chn].sustain = d2; if (d2) { - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].status == sVS_PLAYING && voice[i].channel == chn) { voice[i].status = sVS_SUSTAINED; } } } else { - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].status == sVS_SUSTAINED && voice[i].channel == chn) { voice[i].status = sVS_UNUSED; SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64); @@ -1240,7 +1243,7 @@ case 0x0000: if (channel[chn].benderRange != d2) { channel[chn].benderRange = d2; - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].channel == chn) { SEQ_BENDER_RANGE(wDevID, i, channel[chn].benderRange); } @@ -1250,7 +1253,7 @@ case 0x7F7F: channel[chn].benderRange = 2; - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].channel == chn) { SEQ_BENDER_RANGE(wDevID, i, channel[chn].benderRange); } @@ -1269,7 +1272,7 @@ /* FIXME: I don't know if I have to take care of the channel * for this control ? */ - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].status != sVS_UNUSED && voice[i].channel == chn) { voice[i].status = sVS_UNUSED; SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64); @@ -1280,7 +1283,7 @@ /* FIXME: I don't know if I have to take care of the channel * for this control ? */ - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].status == sVS_PLAYING && voice[i].channel == chn) { voice[i].status = sVS_UNUSED; SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64); @@ -1297,7 +1300,7 @@ channel[chn].program = d1; break; case MIDI_CHN_PRESSURE: - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].status != sVS_UNUSED && voice[i].channel == chn) { SEQ_KEY_PRESSURE(wDevID, i, voice[i].note, d1); } @@ -1305,7 +1308,7 @@ break; case MIDI_PITCH_BEND: channel[chn].bender = (d2 << 7) + d1; - for (i = 0; i < midiOutDevices[wDevID]->wVoices; i++) { + for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) { if (voice[i].channel == chn) { SEQ_BENDER(wDevID, i, channel[chn].bender); } @@ -1328,7 +1331,7 @@ break; case MOD_MIDIPORT: { - int dev = wDevID - MODM_NUMFMSYNTHDEVS; + int dev = wDevID - MODM_NumFMSynthDevs; if (dev < 0) { WARN("Internal error on devID (%u) !\n", wDevID); return MIDIERR_NODEVICE; @@ -1392,7 +1395,7 @@ break; default: WARN("Technology not supported (yet) %d !\n", - midiOutDevices[wDevID]->wTechnology); + MidiOutDev[wDevID].caps.wTechnology); return MMSYSERR_NOTENABLED; } @@ -1411,6 +1414,9 @@ TRACE("(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize); + if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID; + if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE; + if (midiSeqFD == -1) { WARN("can't play !\n"); return MIDIERR_NODEVICE; @@ -1441,23 +1447,23 @@ lpData[0], lpData[1], lpData[2], lpData[lpMidiHdr->dwBufferLength-3], lpData[lpMidiHdr->dwBufferLength-2], lpData[lpMidiHdr->dwBufferLength-1]); - switch (midiOutDevices[wDevID]->wTechnology) { + switch (MidiOutDev[wDevID].caps.wTechnology) { case MOD_FMSYNTH: /* FIXME: I don't think there is much to do here */ break; case MOD_MIDIPORT: if (lpData[0] != 0xF0) { /* Send end of System Exclusive */ - SEQ_MIDIOUT(wDevID - MODM_NUMFMSYNTHDEVS, 0xF0); + SEQ_MIDIOUT(wDevID - MODM_NumFMSynthDevs, 0xF0); WARN("Adding missing 0xF0 marker at the beginning of " "system exclusive byte stream\n"); } for (count = 0; count < lpMidiHdr->dwBytesRecorded; count++) { - SEQ_MIDIOUT(wDevID - MODM_NUMFMSYNTHDEVS, lpData[count]); + SEQ_MIDIOUT(wDevID - MODM_NumFMSynthDevs, lpData[count]); } if (lpData[count - 1] != 0xF7) { /* Send end of System Exclusive */ - SEQ_MIDIOUT(wDevID - MODM_NUMFMSYNTHDEVS, 0xF7); + SEQ_MIDIOUT(wDevID - MODM_NumFMSynthDevs, 0xF7); WARN("Adding missing 0xF7 marker at the end of " "system exclusive byte stream\n"); } @@ -1465,7 +1471,7 @@ break; default: WARN("Technology not supported (yet) %d !\n", - midiOutDevices[wDevID]->wTechnology); + MidiOutDev[wDevID].caps.wTechnology); return MMSYSERR_NOTENABLED; } @@ -1537,6 +1543,9 @@ TRACE("(%04X);\n", wDevID); + if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID; + if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE; + /* stop all notes */ /* FIXME: check if 0x78B0 is channel dependant or not. I coded it so that * it's channel dependent... @@ -1585,7 +1594,7 @@ case MIDM_GETDEVCAPS: return midGetDevCaps(wDevID, (LPMIDIINCAPSA)dwParam1,dwParam2); case MIDM_GETNUMDEVS: - return MIDM_NUMDEVS; + return MIDM_NumDevs; case MIDM_RESET: return midReset(wDevID); case MIDM_START: @@ -1631,7 +1640,7 @@ case MODM_GETDEVCAPS: return modGetDevCaps(wDevID, (LPMIDIOUTCAPSA)dwParam1, dwParam2); case MODM_GETNUMDEVS: - return MODM_NUMDEVS; + return MODM_NumDevs; case MODM_GETVOLUME: return 0; case MODM_SETVOLUME: