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

Andrew Eikum aeikum at codeweavers.com
Thu Apr 21 08:42:18 CDT 2022


Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>

On Thu, Apr 21, 2022 at 07:52:16AM +0100, Huw Davies wrote:
> 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