[PATCH 2/4] wineoss: Move MODM_DATA to the unixlib.

Huw Davies huw at codeweavers.com
Thu Apr 21 01:52:16 CDT 2022


Signed-off-by: Huw Davies <huw at codeweavers.com>
---
 dlls/wineoss.drv/midi.c    | 338 +------------------------------------
 dlls/wineoss.drv/oss.c     |   1 -
 dlls/wineoss.drv/ossmidi.c | 301 ++++++++++++++++++++++++++++++++-
 dlls/wineoss.drv/unixlib.h |   9 -
 4 files changed, 301 insertions(+), 348 deletions(-)

diff --git a/dlls/wineoss.drv/midi.c b/dlls/wineoss.drv/midi.c
index 70bc4b7b9bd..1751af2349e 100644
--- a/dlls/wineoss.drv/midi.c
+++ b/dlls/wineoss.drv/midi.c
@@ -692,46 +692,6 @@ static DWORD midStop(WORD wDevID)
 
 /*-----------------------------------------------------------------------*/
 
-typedef struct sVoice {
-    int			note;			/* 0 means not used */
-    int			channel;
-    unsigned		cntMark : 30,
-	                status : 2;
-#define sVS_UNUSED	0
-#define sVS_PLAYING	1
-#define sVS_SUSTAINED	2
-} sVoice;
-
-typedef struct sChannel {
-    int			program;
-
-    int			bender;
-    int			benderRange;
-    /* controllers */
-    int			bank;		/* CTL_BANK_SELECT */
-    int			volume;		/* CTL_MAIN_VOLUME */
-    int			balance;	/* CTL_BALANCE     */
-    int			expression;	/* CTL_EXPRESSION  */
-    int			sustain;	/* CTL_SUSTAIN     */
-
-    unsigned char	nrgPmtMSB;	/* Non register Parameters */
-    unsigned char	nrgPmtLSB;
-    unsigned char	regPmtMSB;	/* Non register Parameters */
-    unsigned char	regPmtLSB;
-} sChannel;
-
-typedef struct sFMextra {
-    unsigned		counter;
-    int			drumSetMask;
-    sChannel		channel[16];	/* MIDI has only 16 channels */
-    sVoice		voice[1];	/* dyn allocated according to sound card */
-    /* do not append fields below voice[1] since the size of this structure
-     * depends on the number of available voices on the FM synth...
-     */
-} sFMextra;
-
-#define		IS_DRUM_CHANNEL(_xtra, _chn)	((_xtra)->drumSetMask & (1 << (_chn)))
-
 /**************************************************************************
  * 				modGetDevCaps			[internal]
  */
@@ -747,295 +707,6 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
     return MMSYSERR_NOERROR;
 }
 
-static UINT midi_out_fm_data(WORD dev_id, UINT data)
-{
-    struct midi_dest *dest = MidiOutDev + dev_id;
-    WORD evt = LOBYTE(LOWORD(data));
-    WORD d1  = HIBYTE(LOWORD(data));
-    WORD d2  = LOBYTE(HIWORD(data));
-    sFMextra *extra = dest->lpExtra;
-    sVoice *voice = extra->voice;
-    sChannel *channel = extra->channel;
-    int chn = (evt & 0x0F), i, nv;
-
-    /* FIXME: chorus depth controller is not used */
-
-    switch (evt & 0xF0)
-    {
-    case MIDI_NOTEOFF:
-        for (i = 0; i < dest->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;
-                SEQ_STOP_NOTE(dev_id, i, d1, d2);
-            }
-        }
-        break;
-    case MIDI_NOTEON:
-        if (d2 == 0) /* note off if velocity == 0 */
-        {
-            for (i = 0; i < dest->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;
-                    SEQ_STOP_NOTE(dev_id, i, d1, 64);
-                }
-            }
-            break;
-        }
-        /* finding out in this order :
-         * - an empty voice
-         * - if replaying the same note on the same channel
-         * - the older voice (LRU)
-         */
-        for (i = nv = 0; i < dest->caps.wVoices; i++)
-        {
-            if (voice[i].status == sVS_UNUSED || (voice[i].note == d1 && voice[i].channel == chn))
-            {
-                nv = i;
-                break;
-            }
-            if (voice[i].cntMark < voice[0].cntMark)
-                nv = i;
-        }
-        TRACE("playing on voice=%d, pgm=%d, pan=0x%02X, vol=0x%02X, bender=0x%02X, note=0x%02X, vel=0x%02X\n",
-              nv, channel[chn].program, channel[chn].balance, channel[chn].volume, channel[chn].bender, d1, d2);
-
-        SEQ_SET_PATCH(dev_id, nv, IS_DRUM_CHANNEL(extra, chn) ?
-                      (128 + d1) : channel[chn].program);
-        SEQ_BENDER_RANGE(dev_id, nv, channel[chn].benderRange * 100);
-        SEQ_BENDER(dev_id, nv, channel[chn].bender);
-        SEQ_CONTROL(dev_id, nv, CTL_PAN, channel[chn].balance);
-        SEQ_CONTROL(dev_id, nv, CTL_EXPRESSION, channel[chn].expression);
-        SEQ_START_NOTE(dev_id, nv, d1, d2);
-        voice[nv].status = channel[chn].sustain ? sVS_SUSTAINED : sVS_PLAYING;
-        voice[nv].note = d1;
-        voice[nv].channel = chn;
-        voice[nv].cntMark = extra->counter++;
-        break;
-    case MIDI_KEY_PRESSURE:
-        for (i = 0; i < dest->caps.wVoices; i++)
-            if (voice[i].status != sVS_UNUSED && voice[i].channel == chn && voice[i].note == d1)
-                SEQ_KEY_PRESSURE(dev_id, i, d1, d2);
-        break;
-    case MIDI_CTL_CHANGE:
-        switch (d1)
-        {
-        case CTL_BANK_SELECT: channel[chn].bank = d2; break;
-        case CTL_MAIN_VOLUME: channel[chn].volume = d2; break;
-        case CTL_PAN:         channel[chn].balance = d2; break;
-        case CTL_EXPRESSION:  channel[chn].expression = d2; break;
-        case CTL_SUSTAIN:     channel[chn].sustain = d2;
-            if (d2)
-            {
-                for (i = 0; i < dest->caps.wVoices; i++)
-                    if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
-                        voice[i].status = sVS_SUSTAINED;
-            }
-            else
-            {
-                for (i = 0; i < dest->caps.wVoices; i++)
-                {
-                    if (voice[i].status == sVS_SUSTAINED && voice[i].channel == chn)
-                    {
-                        voice[i].status = sVS_UNUSED;
-                        SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
-                    }
-                }
-            }
-            break;
-        case CTL_NONREG_PARM_NUM_LSB: channel[chn].nrgPmtLSB = d2; break;
-        case CTL_NONREG_PARM_NUM_MSB: channel[chn].nrgPmtMSB = d2; break;
-        case CTL_REGIST_PARM_NUM_LSB: channel[chn].regPmtLSB = d2; break;
-        case CTL_REGIST_PARM_NUM_MSB: channel[chn].regPmtMSB = d2; break;
-        case CTL_DATA_ENTRY:
-            switch ((channel[chn].regPmtMSB << 8) | channel[chn].regPmtLSB)
-            {
-            case 0x0000:
-                if (channel[chn].benderRange != d2)
-                {
-                    channel[chn].benderRange = d2;
-                    for (i = 0; i < dest->caps.wVoices; i++)
-                        if (voice[i].channel == chn)
-                            SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
-                }
-                break;
-
-            case 0x7F7F:
-                channel[chn].benderRange = 2;
-                for (i = 0; i < dest->caps.wVoices; i++)
-                    if (voice[i].channel == chn)
-                        SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
-                break;
-            default:
-                TRACE("Data entry: regPmt=0x%02x%02x, nrgPmt=0x%02x%02x with %x\n",
-                      channel[chn].regPmtMSB, channel[chn].regPmtLSB,
-                      channel[chn].nrgPmtMSB, channel[chn].nrgPmtLSB, d2);
-                break;
-            }
-            break;
-
-        case 0x78: /* all sounds off */
-            /* FIXME: I don't know if I have to take care of the channel for this control? */
-            for (i = 0; i < dest->caps.wVoices; i++)
-            {
-                if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
-                {
-                    voice[i].status = sVS_UNUSED;
-                    SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
-                }
-            }
-            break;
-        case 0x7B: /* all notes off */
-            /* FIXME: I don't know if I have to take care of the channel for this control? */
-            for (i = 0; i < dest->caps.wVoices; i++)
-            {
-                if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
-                {
-                    voice[i].status = sVS_UNUSED;
-                    SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
-                }
-            }
-            break;
-        default:
-            TRACE("Dropping MIDI control event 0x%02x(%02x) on channel %d\n", d1, d2, chn);
-            break;
-        }
-        break;
-    case MIDI_PGM_CHANGE:
-        channel[chn].program = d1;
-        break;
-    case MIDI_CHN_PRESSURE:
-        for (i = 0; i < dest->caps.wVoices; i++)
-            if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
-                SEQ_KEY_PRESSURE(dev_id, i, voice[i].note, d1);
-
-        break;
-    case MIDI_PITCH_BEND:
-        channel[chn].bender = (d2 << 7) + d1;
-        for (i = 0; i < dest->caps.wVoices; i++)
-            if (voice[i].channel == chn)
-                SEQ_BENDER(dev_id, i, channel[chn].bender);
-        break;
-    case MIDI_SYSTEM_PREFIX:
-        switch (evt & 0x0F)
-        {
-        case 0x0F: /* Reset */
-            OSS_CALL(midi_out_fm_reset, (void *)(UINT_PTR)dev_id);
-            break;
-        default:
-            WARN("Unsupported (yet) system event %02x\n", evt & 0x0F);
-        }
-        break;
-    default:
-        WARN("Internal error, shouldn't happen (event=%08x)\n", evt & 0xF0);
-        return MMSYSERR_NOTENABLED;
-    }
-
-    SEQ_DUMPBUF();
-    return MMSYSERR_NOERROR;
-}
-
-static UINT midi_out_port_data(WORD dev_id, UINT data)
-{
-    WORD evt = LOBYTE(LOWORD(data));
-    WORD d1  = HIBYTE(LOWORD(data));
-    WORD d2  = LOBYTE(HIWORD(data));
-    int dev = dev_id - MODM_NumFMSynthDevs;
-
-    if (dev < 0)
-    {
-        WARN("Internal error on devID (%u) !\n", dev_id);
-        return MIDIERR_NODEVICE;
-    }
-
-    switch (evt & 0xF0)
-    {
-    case MIDI_NOTEOFF:
-    case MIDI_NOTEON:
-    case MIDI_KEY_PRESSURE:
-    case MIDI_CTL_CHANGE:
-    case MIDI_PITCH_BEND:
-        SEQ_MIDIOUT(dev, evt);
-        SEQ_MIDIOUT(dev, d1);
-        SEQ_MIDIOUT(dev, d2);
-        break;
-    case MIDI_PGM_CHANGE:
-    case MIDI_CHN_PRESSURE:
-        SEQ_MIDIOUT(dev, evt);
-        SEQ_MIDIOUT(dev, d1);
-        break;
-    case MIDI_SYSTEM_PREFIX:
-        switch (evt & 0x0F)
-        {
-        case 0x00: /* System Exclusive, don't do it on MODM_DATA, should require MODM_LONGDATA */
-        case 0x04: /* Undefined. */
-        case 0x05: /* Undefined. */
-        case 0x07: /* End of Exclusive. */
-        case 0x09: /* Undefined. */
-        case 0x0D: /* Undefined. */
-            break;
-        case 0x06: /* Tune Request */
-        case 0x08: /* Timing Clock. */
-        case 0x0A: /* Start. */
-        case 0x0B: /* Continue */
-        case 0x0C: /* Stop */
-        case 0x0E: /* Active Sensing. */
-            SEQ_MIDIOUT(dev, evt);
-            break;
-        case 0x0F: /* Reset */
-            SEQ_MIDIOUT(dev, MIDI_SYSTEM_PREFIX);
-            SEQ_MIDIOUT(dev, 0x7e);
-            SEQ_MIDIOUT(dev, 0x7f);
-            SEQ_MIDIOUT(dev, 0x09);
-            SEQ_MIDIOUT(dev, 0x01);
-            SEQ_MIDIOUT(dev, 0xf7);
-            break;
-        case 0x01: /* MTC Quarter frame */
-        case 0x03: /* Song Select. */
-            SEQ_MIDIOUT(dev, evt);
-            SEQ_MIDIOUT(dev, d1);
-        case 0x02: /* Song Position Pointer. */
-            SEQ_MIDIOUT(dev, evt);
-            SEQ_MIDIOUT(dev, d1);
-            SEQ_MIDIOUT(dev, d2);
-        }
-        break;
-    }
-
-    SEQ_DUMPBUF();
-    return MMSYSERR_NOERROR;
-}
-
-/**************************************************************************
- * 			modData					[internal]
- */
-static DWORD modData(WORD wDevID, DWORD dwParam)
-{
-    TRACE("(%04X, %08X);\n", wDevID, dwParam);
-
-    if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
-    if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;
-
-    if (MidiOutDev[wDevID].fd == -1) {
-	WARN("can't play !\n");
-	return MIDIERR_NODEVICE;
-    }
-    switch (MidiOutDev[wDevID].caps.wTechnology) {
-    case MOD_FMSYNTH:
-        return midi_out_fm_data(wDevID, dwParam);
-    case MOD_MIDIPORT:
-        return midi_out_port_data(wDevID, dwParam);
-    }
-
-    WARN("Technology not supported (yet) %d !\n",
-         MidiOutDev[wDevID].caps.wTechnology);
-    return MMSYSERR_NOTENABLED;
-}
-
 /**************************************************************************
  *		modLongData					[internal]
  */
@@ -1164,6 +835,9 @@ static DWORD modGetVolume(WORD wDevID, DWORD* lpdwVolume)
     return (MidiOutDev[wDevID].caps.dwSupport & MIDICAPS_VOLUME) ? 0 : MMSYSERR_NOTSUPPORTED;
 }
 
+DWORD WINAPI OSS_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
+			    DWORD_PTR dwParam1, DWORD_PTR dwParam2);
+
 /**************************************************************************
  * 			modReset				[internal]
  */
@@ -1182,9 +856,9 @@ static DWORD modReset(WORD wDevID)
      */
     for (chn = 0; chn < 16; chn++) {
 	/* turn off every note */
-	modData(wDevID, 0x7800 | MIDI_CTL_CHANGE | chn);
+	OSS_modMessage(wDevID, MODM_DATA, 0, 0x7800 | MIDI_CTL_CHANGE | chn, 0);
 	/* remove sustain on all channels */
-	modData(wDevID, (CTL_SUSTAIN << 8) | MIDI_CTL_CHANGE | chn);
+	OSS_modMessage(wDevID, MODM_DATA, 0, (CTL_SUSTAIN << 8) | MIDI_CTL_CHANGE | chn, 0);
     }
     /* FIXME: the LongData buffers must also be returned to the app */
     return MMSYSERR_NOERROR;
@@ -1255,8 +929,6 @@ DWORD WINAPI OSS_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
         return OSS_MidiInit();
     case DRVM_EXIT:
         return OSS_MidiExit();
-    case MODM_DATA:
-	return modData(wDevID, dwParam1);
     case MODM_LONGDATA:
 	return modLongData(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
     case MODM_PREPARE:
diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c
index 1bd5ddb5762..db2f705a0c5 100644
--- a/dlls/wineoss.drv/oss.c
+++ b/dlls/wineoss.drv/oss.c
@@ -1409,5 +1409,4 @@ unixlib_entry_t __wine_unix_call_funcs[] =
     midi_out_message,
 
     midi_seq_open,
-    midi_out_fm_reset,
 };
diff --git a/dlls/wineoss.drv/ossmidi.c b/dlls/wineoss.drv/ossmidi.c
index 613b070fde5..ee83da8bfcd 100644
--- a/dlls/wineoss.drv/ossmidi.c
+++ b/dlls/wineoss.drv/ossmidi.c
@@ -93,6 +93,8 @@ typedef struct sFMextra
      */
 } sFMextra;
 
+#define IS_DRUM_CHANNEL(_xtra, _chn) ((_xtra)->drumSetMask & (1 << (_chn)))
+
 WINE_DEFAULT_DEBUG_CHANNEL(midi);
 
 static int oss_to_win_device_type(int type)
@@ -458,9 +460,8 @@ static int midi_out_fm_load(WORD dev_id, int fd)
     return 0;
 }
 
-NTSTATUS midi_out_fm_reset(void *args)
+static void midi_out_fm_reset(WORD dev_id)
 {
-    WORD dev_id = (WORD)(UINT_PTR)args;
     struct midi_dest *dest = dests + dev_id;
     sFMextra *extra = dest->lpExtra;
     sVoice *voice = extra->voice;
@@ -492,8 +493,6 @@ NTSTATUS midi_out_fm_reset(void *args)
     extra->counter = 0;
     extra->drumSetMask = 1 << 9; /* channel 10 is normally drums, sometimes 16 also */
     SEQ_DUMPBUF();
-
-    return STATUS_SUCCESS;
 }
 
 static void set_out_notify(struct notify_context *notify, struct midi_dest *dest, WORD dev_id, WORD msg,
@@ -572,7 +571,7 @@ static UINT midi_out_open(WORD dev_id, MIDIOPENDESC *midi_desc, UINT flags, stru
             free(extra);
             return MMSYSERR_ERROR;
         }
-        midi_out_fm_reset((void *)(UINT_PTR)dev_id);
+        midi_out_fm_reset(dev_id);
         break;
     }
     case MOD_MIDIPORT:
@@ -645,6 +644,295 @@ static UINT midi_out_close(WORD dev_id, struct notify_context *notify)
     return MMSYSERR_NOERROR;
 }
 
+static UINT midi_out_fm_data(WORD dev_id, UINT data)
+{
+    struct midi_dest *dest = dests + dev_id;
+    WORD evt = LOBYTE(LOWORD(data));
+    WORD d1  = HIBYTE(LOWORD(data));
+    WORD d2  = LOBYTE(HIWORD(data));
+    sFMextra *extra = dest->lpExtra;
+    sVoice *voice = extra->voice;
+    sChannel *channel = extra->channel;
+    int chn = (evt & 0x0F), i, nv;
+
+    /* FIXME: chorus depth controller is not used */
+
+    switch (evt & 0xF0)
+    {
+    case MIDI_NOTEOFF:
+        for (i = 0; i < dest->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;
+                SEQ_STOP_NOTE(dev_id, i, d1, d2);
+            }
+        }
+        break;
+    case MIDI_NOTEON:
+        if (d2 == 0) /* note off if velocity == 0 */
+        {
+            for (i = 0; i < dest->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;
+                    SEQ_STOP_NOTE(dev_id, i, d1, 64);
+                }
+            }
+            break;
+        }
+        /* finding out in this order :
+         * - an empty voice
+         * - if replaying the same note on the same channel
+         * - the older voice (LRU)
+         */
+        for (i = nv = 0; i < dest->caps.wVoices; i++)
+        {
+            if (voice[i].status == sVS_UNUSED || (voice[i].note == d1 && voice[i].channel == chn))
+            {
+                nv = i;
+                break;
+            }
+            if (voice[i].cntMark < voice[0].cntMark)
+                nv = i;
+        }
+        TRACE("playing on voice=%d, pgm=%d, pan=0x%02X, vol=0x%02X, bender=0x%02X, note=0x%02X, vel=0x%02X\n",
+              nv, channel[chn].program, channel[chn].balance, channel[chn].volume, channel[chn].bender, d1, d2);
+
+        SEQ_SET_PATCH(dev_id, nv, IS_DRUM_CHANNEL(extra, chn) ?
+                      (128 + d1) : channel[chn].program);
+        SEQ_BENDER_RANGE(dev_id, nv, channel[chn].benderRange * 100);
+        SEQ_BENDER(dev_id, nv, channel[chn].bender);
+        SEQ_CONTROL(dev_id, nv, CTL_PAN, channel[chn].balance);
+        SEQ_CONTROL(dev_id, nv, CTL_EXPRESSION, channel[chn].expression);
+        SEQ_START_NOTE(dev_id, nv, d1, d2);
+        voice[nv].status = channel[chn].sustain ? sVS_SUSTAINED : sVS_PLAYING;
+        voice[nv].note = d1;
+        voice[nv].channel = chn;
+        voice[nv].cntMark = extra->counter++;
+        break;
+    case MIDI_KEY_PRESSURE:
+        for (i = 0; i < dest->caps.wVoices; i++)
+            if (voice[i].status != sVS_UNUSED && voice[i].channel == chn && voice[i].note == d1)
+                SEQ_KEY_PRESSURE(dev_id, i, d1, d2);
+        break;
+    case MIDI_CTL_CHANGE:
+        switch (d1)
+        {
+        case CTL_BANK_SELECT: channel[chn].bank = d2; break;
+        case CTL_MAIN_VOLUME: channel[chn].volume = d2; break;
+        case CTL_PAN:         channel[chn].balance = d2; break;
+        case CTL_EXPRESSION:  channel[chn].expression = d2; break;
+        case CTL_SUSTAIN:     channel[chn].sustain = d2;
+            if (d2)
+            {
+                for (i = 0; i < dest->caps.wVoices; i++)
+                    if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
+                        voice[i].status = sVS_SUSTAINED;
+            }
+            else
+            {
+                for (i = 0; i < dest->caps.wVoices; i++)
+                {
+                    if (voice[i].status == sVS_SUSTAINED && voice[i].channel == chn)
+                    {
+                        voice[i].status = sVS_UNUSED;
+                        SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
+                    }
+                }
+            }
+            break;
+        case CTL_NONREG_PARM_NUM_LSB: channel[chn].nrgPmtLSB = d2; break;
+        case CTL_NONREG_PARM_NUM_MSB: channel[chn].nrgPmtMSB = d2; break;
+        case CTL_REGIST_PARM_NUM_LSB: channel[chn].regPmtLSB = d2; break;
+        case CTL_REGIST_PARM_NUM_MSB: channel[chn].regPmtMSB = d2; break;
+        case CTL_DATA_ENTRY:
+            switch ((channel[chn].regPmtMSB << 8) | channel[chn].regPmtLSB)
+            {
+            case 0x0000:
+                if (channel[chn].benderRange != d2)
+                {
+                    channel[chn].benderRange = d2;
+                    for (i = 0; i < dest->caps.wVoices; i++)
+                        if (voice[i].channel == chn)
+                            SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
+                }
+                break;
+
+            case 0x7F7F:
+                channel[chn].benderRange = 2;
+                for (i = 0; i < dest->caps.wVoices; i++)
+                    if (voice[i].channel == chn)
+                        SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
+                break;
+            default:
+                TRACE("Data entry: regPmt=0x%02x%02x, nrgPmt=0x%02x%02x with %x\n",
+                      channel[chn].regPmtMSB, channel[chn].regPmtLSB,
+                      channel[chn].nrgPmtMSB, channel[chn].nrgPmtLSB, d2);
+                break;
+            }
+            break;
+
+        case 0x78: /* all sounds off */
+            /* FIXME: I don't know if I have to take care of the channel for this control? */
+            for (i = 0; i < dest->caps.wVoices; i++)
+            {
+                if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
+                {
+                    voice[i].status = sVS_UNUSED;
+                    SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
+                }
+            }
+            break;
+        case 0x7B: /* all notes off */
+            /* FIXME: I don't know if I have to take care of the channel for this control? */
+            for (i = 0; i < dest->caps.wVoices; i++)
+            {
+                if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
+                {
+                    voice[i].status = sVS_UNUSED;
+                    SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
+                }
+            }
+            break;
+        default:
+            TRACE("Dropping MIDI control event 0x%02x(%02x) on channel %d\n", d1, d2, chn);
+            break;
+        }
+        break;
+    case MIDI_PGM_CHANGE:
+        channel[chn].program = d1;
+        break;
+    case MIDI_CHN_PRESSURE:
+        for (i = 0; i < dest->caps.wVoices; i++)
+            if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
+                SEQ_KEY_PRESSURE(dev_id, i, voice[i].note, d1);
+
+        break;
+    case MIDI_PITCH_BEND:
+        channel[chn].bender = (d2 << 7) + d1;
+        for (i = 0; i < dest->caps.wVoices; i++)
+            if (voice[i].channel == chn)
+                SEQ_BENDER(dev_id, i, channel[chn].bender);
+        break;
+    case MIDI_SYSTEM_PREFIX:
+        switch (evt & 0x0F)
+        {
+        case 0x0F: /* Reset */
+            midi_out_fm_reset(dev_id);
+            break;
+        default:
+            WARN("Unsupported (yet) system event %02x\n", evt & 0x0F);
+        }
+        break;
+    default:
+        WARN("Internal error, shouldn't happen (event=%08x)\n", evt & 0xF0);
+        return MMSYSERR_NOTENABLED;
+    }
+
+    SEQ_DUMPBUF();
+    return MMSYSERR_NOERROR;
+}
+
+static UINT midi_out_port_data(WORD dev_id, UINT data)
+{
+    WORD evt = LOBYTE(LOWORD(data));
+    WORD d1  = HIBYTE(LOWORD(data));
+    WORD d2  = LOBYTE(HIWORD(data));
+    int dev = dev_id - num_synths;
+
+    if (dev < 0)
+    {
+        WARN("Internal error on devID (%u) !\n", dev_id);
+        return MIDIERR_NODEVICE;
+    }
+
+    switch (evt & 0xF0)
+    {
+    case MIDI_NOTEOFF:
+    case MIDI_NOTEON:
+    case MIDI_KEY_PRESSURE:
+    case MIDI_CTL_CHANGE:
+    case MIDI_PITCH_BEND:
+        SEQ_MIDIOUT(dev, evt);
+        SEQ_MIDIOUT(dev, d1);
+        SEQ_MIDIOUT(dev, d2);
+        break;
+    case MIDI_PGM_CHANGE:
+    case MIDI_CHN_PRESSURE:
+        SEQ_MIDIOUT(dev, evt);
+        SEQ_MIDIOUT(dev, d1);
+        break;
+    case MIDI_SYSTEM_PREFIX:
+        switch (evt & 0x0F)
+        {
+        case 0x00: /* System Exclusive, don't do it on MODM_DATA, should require MODM_LONGDATA */
+        case 0x04: /* Undefined. */
+        case 0x05: /* Undefined. */
+        case 0x07: /* End of Exclusive. */
+        case 0x09: /* Undefined. */
+        case 0x0D: /* Undefined. */
+            break;
+        case 0x06: /* Tune Request */
+        case 0x08: /* Timing Clock. */
+        case 0x0A: /* Start. */
+        case 0x0B: /* Continue */
+        case 0x0C: /* Stop */
+        case 0x0E: /* Active Sensing. */
+            SEQ_MIDIOUT(dev, evt);
+            break;
+        case 0x0F: /* Reset */
+            SEQ_MIDIOUT(dev, MIDI_SYSTEM_PREFIX);
+            SEQ_MIDIOUT(dev, 0x7e);
+            SEQ_MIDIOUT(dev, 0x7f);
+            SEQ_MIDIOUT(dev, 0x09);
+            SEQ_MIDIOUT(dev, 0x01);
+            SEQ_MIDIOUT(dev, 0xf7);
+            break;
+        case 0x01: /* MTC Quarter frame */
+        case 0x03: /* Song Select. */
+            SEQ_MIDIOUT(dev, evt);
+            SEQ_MIDIOUT(dev, d1);
+        case 0x02: /* Song Position Pointer. */
+            SEQ_MIDIOUT(dev, evt);
+            SEQ_MIDIOUT(dev, d1);
+            SEQ_MIDIOUT(dev, d2);
+        }
+        break;
+    }
+
+    SEQ_DUMPBUF();
+    return MMSYSERR_NOERROR;
+}
+
+static UINT midi_out_data(WORD dev_id, UINT data)
+{
+    struct midi_dest *dest;
+
+    TRACE("(%04X, %08X);\n", dev_id, data);
+
+    if (dev_id >= num_dests) return MMSYSERR_BADDEVICEID;
+    dest = dests + dev_id;
+    if (!dest->bEnabled) return MIDIERR_NODEVICE;
+
+    if (dest->fd == -1)
+    {
+        WARN("can't play !\n");
+        return MIDIERR_NODEVICE;
+    }
+    switch (dest->caps.wTechnology)
+    {
+    case MOD_FMSYNTH:
+        return midi_out_fm_data(dev_id, data);
+    case MOD_MIDIPORT:
+        return midi_out_port_data(dev_id, data);
+    }
+
+    WARN("Technology not supported (yet) %d !\n", dest->caps.wTechnology);
+    return MMSYSERR_NOTENABLED;
+}
 
 NTSTATUS midi_out_message(void *args)
 {
@@ -665,6 +953,9 @@ NTSTATUS midi_out_message(void *args)
     case MODM_CLOSE:
         *params->err = midi_out_close(params->dev_id, params->notify);
         break;
+    case MODM_DATA:
+        *params->err = midi_out_data(params->dev_id, params->param_1);
+        break;
     default:
         TRACE("Unsupported message\n");
         *params->err = MMSYSERR_NOTSUPPORTED;
diff --git a/dlls/wineoss.drv/unixlib.h b/dlls/wineoss.drv/unixlib.h
index 75506d445bc..d56e11b8d23 100644
--- a/dlls/wineoss.drv/unixlib.h
+++ b/dlls/wineoss.drv/unixlib.h
@@ -276,13 +276,6 @@ struct midi_seq_open_params
     int fd;
 };
 
-struct midi_out_fm_load_params
-{
-    WORD dev_id;
-    int fd;
-    int ret;
-};
-
 enum oss_funcs
 {
     oss_test_connect,
@@ -312,13 +305,11 @@ enum oss_funcs
     oss_midi_out_message,
 
     oss_midi_seq_open, /* temporary */
-    oss_midi_out_fm_reset,
 };
 
 NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
 NTSTATUS midi_out_message(void *args) DECLSPEC_HIDDEN;
 NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN;
-NTSTATUS midi_out_fm_reset(void *args) DECLSPEC_HIDDEN;
 
 extern unixlib_handle_t oss_handle;
 
-- 
2.25.1




More information about the wine-devel mailing list