Midi in OSS

Eric Pouech eric.pouech at wanadoo.fr
Tue Nov 19 13:59:55 CST 2002


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+
-------------- next part --------------
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:


More information about the wine-patches mailing list