[PATCH 3/3] wineoss: Move midi_init to the unixlib.
Andrew Eikum
aeikum at codeweavers.com
Tue Apr 19 08:40:46 CDT 2022
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
On Tue, Apr 19, 2022 at 07:38:44AM +0100, Huw Davies wrote:
> Signed-off-by: Huw Davies <huw at codeweavers.com>
> ---
> dlls/wineoss.drv/Makefile.in | 3 +-
> dlls/wineoss.drv/midi.c | 276 +++--------------------------
> dlls/wineoss.drv/oss.c | 1 +
> dlls/wineoss.drv/ossmidi.c | 335 +++++++++++++++++++++++++++++++++++
> dlls/wineoss.drv/unixlib.h | 38 ++++
> 5 files changed, 403 insertions(+), 250 deletions(-)
> create mode 100644 dlls/wineoss.drv/ossmidi.c
>
> diff --git a/dlls/wineoss.drv/Makefile.in b/dlls/wineoss.drv/Makefile.in
> index d48db94b929..04b438da71e 100644
> --- a/dlls/wineoss.drv/Makefile.in
> +++ b/dlls/wineoss.drv/Makefile.in
> @@ -13,4 +13,5 @@ C_SRCS = \
> midipatch.c \
> mmaux.c \
> mmdevdrv.c \
> - oss.c
> + oss.c \
> + ossmidi.c
> diff --git a/dlls/wineoss.drv/midi.c b/dlls/wineoss.drv/midi.c
> index 1cf19b7be1a..626b3d43d83 100644
> --- a/dlls/wineoss.drv/midi.c
> +++ b/dlls/wineoss.drv/midi.c
> @@ -1,15 +1,10 @@
> -/* -*- tab-width: 8; c-basic-offset: 4 -*- */
> -
> /*
> - * Sample MIDI Wine Driver for Open Sound System (basically Linux)
> + * MIDI driver for OSS (PE-side)
> *
> - * Copyright 1994 Martin Ayotte
> - * Copyright 1998 Luiz Otavio L. Zorzella (init procedures)
> - * Copyright 1998/1999 Eric POUECH :
> - * 98/7 changes for making this MIDI driver work on OSS
> - * current support is limited to MIDI ports of OSS systems
> - * 98/9 rewriting MCI code for MIDI
> - * 98/11 split in midi.c and mcimidi.c
> + * Copyright 1994 Martin Ayotte
> + * Copyright 1998 Luiz Otavio L. Zorzella (init procedures)
> + * Copyright 1998, 1999 Eric POUECH
> + * Copyright 2022 Huw Davies
> *
> * This library is free software; you can redistribute it and/or
> * modify it under the terms of the GNU Lesser General Public
> @@ -57,35 +52,19 @@
> #include "winbase.h"
> #include "wingdi.h"
> #include "winuser.h"
> -#include "winnls.h"
> +#include "winternl.h"
> #include "mmddk.h"
> +#include "audioclient.h"
> +
> #include "wine/debug.h"
> +#include "wine/unixlib.h"
> +
> +#include "unixlib.h"
>
> WINE_DEFAULT_DEBUG_CHANNEL(midi);
>
> -typedef struct {
> - int state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
> - MIDIOPENDESC midiDesc;
> - WORD wFlags;
> - LPMIDIHDR lpQueueHdr;
> - unsigned char incoming[3];
> - unsigned char incPrev;
> - char incLen;
> - DWORD startTime;
> - MIDIINCAPSW caps;
> -} WINE_MIDIIN;
> -
> -typedef struct {
> - BOOL bEnabled;
> - MIDIOPENDESC midiDesc;
> - WORD wFlags;
> - LPMIDIHDR lpQueueHdr;
> - void* lpExtra; /* according to port type (MIDI, FM...), extra data when needed */
> - MIDIOUTCAPSW caps;
> -} WINE_MIDIOUT;
> -
> -static WINE_MIDIIN MidiInDev [MAX_MIDIINDRV ];
> -static WINE_MIDIOUT MidiOutDev[MAX_MIDIOUTDRV];
> +static WINE_MIDIIN *MidiInDev;
> +static WINE_MIDIOUT *MidiOutDev;
>
> /* this is the total number of MIDI out devices found (synth and port) */
> static int MODM_NumDevs = 0;
> @@ -119,37 +98,6 @@ static HANDLE hThread;
> static int midiOpenSeq(void);
> static int midiCloseSeq(void);
>
> -/**************************************************************************
> - * MIDI_unixToWindowsDeviceType [internal]
> - *
> - * return the Windows equivalent to a Unix Device Type
> - *
> - */
> -static int MIDI_UnixToWindowsDeviceType(int type)
> -{
> - /* MOD_MIDIPORT output port
> - * MOD_SYNTH generic internal synth
> - * MOD_SQSYNTH square wave internal synth
> - * MOD_FMSYNTH FM internal synth
> - * MOD_MAPPER MIDI mapper
> - * MOD_WAVETABLE hardware wavetable internal synth
> - * MOD_SWSYNTH software internal synth
> - */
> -
> - /* FIXME Is this really the correct equivalence from UNIX to
> - Windows Sound type */
> -
> - switch (type) {
> - case SYNTH_TYPE_FM: return MOD_FMSYNTH;
> - case SYNTH_TYPE_SAMPLE: return MOD_SYNTH;
> - case SYNTH_TYPE_MIDI: return MOD_MIDIPORT;
> - default:
> - ERR("Cannot determine the type of this midi device. "
> - "Assuming FM Synth\n");
> - return MOD_FMSYNTH;
> - }
> -}
> -
> static int MIDI_loadcount;
> /**************************************************************************
> * OSS_MidiInit [internal]
> @@ -158,9 +106,8 @@ static int MIDI_loadcount;
> */
> static LRESULT OSS_MidiInit(void)
> {
> - int i, status, numsynthdevs = 255, nummididevs = 255;
> - struct synth_info sinfo;
> - struct midi_info minfo;
> + struct midi_init_params params;
> + UINT err;
>
> TRACE("(%i)\n", MIDI_loadcount);
> if (MIDI_loadcount++)
> @@ -168,187 +115,18 @@ static LRESULT OSS_MidiInit(void)
>
> TRACE("Initializing the MIDI variables.\n");
>
> - /* try to open device */
> - if (midiOpenSeq() == -1) {
> - return -1;
> - }
> -
> - /* find how many Synth devices are there in the system */
> - status = ioctl(midiSeqFD, SNDCTL_SEQ_NRSYNTHS, &numsynthdevs);
> -
> - if (status == -1) {
> - ERR("ioctl for nr synth failed.\n");
> - midiCloseSeq();
> - return -1;
> - }
> -
> - if (numsynthdevs > MAX_MIDIOUTDRV) {
> - ERR("MAX_MIDIOUTDRV (%d) was enough for the number of devices (%d). "
> - "Some FM devices will not be available.\n",MAX_MIDIOUTDRV,numsynthdevs);
> - numsynthdevs = MAX_MIDIOUTDRV;
> - }
> -
> - for (i = 0; i < numsynthdevs; i++) {
> - /* 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.
> - */
> - MidiOutDev[i].caps.wMid = 0x00FF;
> - MidiOutDev[i].caps.wPid = 0x0001; /* FIXME Product ID */
> - /* Product Version. We simply say "1" */
> - MidiOutDev[i].caps.vDriverVersion = 0x001;
> - /* The following are mandatory for MOD_MIDIPORT */
> - MidiOutDev[i].caps.wChannelMask = 0xFFFF;
> - MidiOutDev[i].caps.wVoices = 0;
> - MidiOutDev[i].caps.wNotes = 0;
> - MidiOutDev[i].caps.dwSupport = 0;
> -
> - sinfo.device = i;
> - status = ioctl(midiSeqFD, SNDCTL_SYNTH_INFO, &sinfo);
> - if (status == -1) {
> - static const WCHAR fmt[] = {'W','i','n','e',' ','O','S','S',' ','M','i','d','i',' ','O','u','t',' ','#','%','d',' ','d','i','s','a','b','l','e','d',0};
> - ERR("ioctl for synth info failed on %d, disabling it.\n", i);
> -
> - wsprintfW(MidiOutDev[i].caps.szPname, fmt, i);
> -
> - MidiOutDev[i].caps.wTechnology = MOD_MIDIPORT;
> - MidiOutDev[i].bEnabled = FALSE;
> - } else {
> - MultiByteToWideChar(CP_UNIXCP, 0, sinfo.name, -1, MidiOutDev[i].caps.szPname,
> - ARRAY_SIZE(MidiOutDev[i].caps.szPname));
> - MidiOutDev[i].caps.wTechnology = MIDI_UnixToWindowsDeviceType(sinfo.synth_type);
> -
> - if (MOD_MIDIPORT != MidiOutDev[i].caps.wTechnology) {
> - /* FIXME Do we have this information?
> - * Assuming the soundcards can handle
> - * MIDICAPS_VOLUME and MIDICAPS_LRVOLUME but
> - * not MIDICAPS_CACHE.
> - */
> - MidiOutDev[i].caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME;
> - MidiOutDev[i].caps.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
> - */
> - 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 supports MIDI in. Not yet supported.\n");
> - }
> - TRACE("SynthOut[%d]\tOSS info: synth type=%d/%d capa=%lx\n",
> - i, sinfo.synth_type, sinfo.synth_subtype, (long)sinfo.capabilities);
> - }
> -
> - TRACE("SynthOut[%d]\tname='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%d\n",
> - i, wine_dbgstr_w(MidiOutDev[i].caps.szPname),
> - MidiOutDev[i].caps.wTechnology,
> - MidiOutDev[i].caps.wVoices, MidiOutDev[i].caps.wNotes,
> - MidiOutDev[i].caps.wChannelMask, MidiOutDev[i].caps.dwSupport);
> - }
> -
> - /* find how many MIDI devices are there in the system */
> - status = ioctl(midiSeqFD, SNDCTL_SEQ_NRMIDIS, &nummididevs);
> - if (status == -1) {
> - ERR("ioctl on nr midi failed.\n");
> - nummididevs = 0;
> - goto wrapup;
> - }
> + params.err = &err;
> + OSS_CALL(midi_init, ¶ms);
>
> - /* FIXME: the two restrictions below could be loosened in some cases */
> - if (numsynthdevs + nummididevs > MAX_MIDIOUTDRV) {
> - ERR("MAX_MIDIOUTDRV was not enough for the number of devices. "
> - "Some MIDI devices will not be available.\n");
> - nummididevs = MAX_MIDIOUTDRV - numsynthdevs;
> + if (!err)
> + {
> + MidiInDev = params.srcs;
> + MidiOutDev = params.dests;
> + MODM_NumDevs = params.num_dests;
> + MODM_NumFMSynthDevs = params.num_synths;
> + MIDM_NumDevs = params.num_srcs;
> }
> -
> - if (nummididevs > MAX_MIDIINDRV) {
> - ERR("MAX_MIDIINDRV (%d) was not enough for the number of devices (%d). "
> - "Some MIDI devices will not be available.\n",MAX_MIDIINDRV,nummididevs);
> - nummididevs = MAX_MIDIINDRV;
> - }
> -
> - for (i = 0; i < nummididevs; i++) {
> - minfo.device = i;
> - status = ioctl(midiSeqFD, SNDCTL_MIDI_INFO, &minfo);
> - if (status == -1) WARN("ioctl on midi info for device %d failed.\n", i);
> -
> - /* 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
> - descriptive minfo.dev_type was not used here.
> - */
> - /* Manufacturer 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 */
> - MidiOutDev[numsynthdevs + i].caps.wMid = 0x00FF;
> - MidiOutDev[numsynthdevs + i].caps.wPid = 0x0001; /* FIXME Product ID */
> - /* Product Version. We simply say "1" */
> - MidiOutDev[numsynthdevs + i].caps.vDriverVersion = 0x001;
> - if (status == -1) {
> - static const WCHAR fmt[] = {'W','i','n','e',' ','O','S','S',' ','M','i','d','i',' ','O','u','t',' ','#','%','d',' ','d','i','s','a','b','l','e','d',0};
> - wsprintfW(MidiOutDev[numsynthdevs + i].caps.szPname, fmt, numsynthdevs + i);
> - MidiOutDev[numsynthdevs + i].bEnabled = FALSE;
> - } else {
> - MultiByteToWideChar(CP_UNIXCP, 0, minfo.name, -1,
> - MidiOutDev[numsynthdevs + i].caps.szPname,
> - ARRAY_SIZE(MidiOutDev[numsynthdevs + i].caps.szPname));
> - MidiOutDev[numsynthdevs + i].bEnabled = TRUE;
> - }
> - MidiOutDev[numsynthdevs + i].caps.wTechnology = MOD_MIDIPORT;
> - MidiOutDev[numsynthdevs + i].caps.wVoices = 0;
> - MidiOutDev[numsynthdevs + i].caps.wNotes = 0;
> - MidiOutDev[numsynthdevs + i].caps.wChannelMask= 0xFFFF;
> - MidiOutDev[numsynthdevs + i].caps.dwSupport = 0;
> -
> - /* 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
> - descriptive minfo.dev_type was 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 */
> - MidiInDev[i].caps.wMid = 0x00FF;
> - MidiInDev[i].caps.wPid = 0x0001; /* FIXME Product ID */
> - /* Product Version. We simply say "1" */
> - MidiInDev[i].caps.vDriverVersion = 0x001;
> - if (status == -1) {
> - static const WCHAR fmt[] = {'W','i','n','e',' ','O','S','S',' ','M','i','d','i',' ','I','n',' ','#','%','d',' ','d','i','s','a','b','l','e','d',0};
> - wsprintfW(MidiInDev[i].caps.szPname, fmt, numsynthdevs + i);
> - MidiInDev[i].state = -1;
> - } else {
> - MultiByteToWideChar(CP_UNIXCP, 0, minfo.name, -1, MidiInDev[i].caps.szPname,
> - ARRAY_SIZE(MidiInDev[i].caps.szPname));
> - MidiInDev[i].state = 0;
> - }
> - MidiInDev[i].caps.dwSupport = 0; /* mandatory with MIDIINCAPS */
> -
> - TRACE("OSS info: midi[%d] dev-type=%d capa=%lx\n"
> - "\tMidiOut[%d] name='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%d\n"
> - "\tMidiIn [%d] name='%s' support=%d\n",
> - i, minfo.dev_type, (long)minfo.capabilities,
> - numsynthdevs + i, wine_dbgstr_w(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, wine_dbgstr_w(MidiInDev[i].caps.szPname), MidiInDev[i].caps.dwSupport);
> - }
> -
> - wrapup:
> - /* windows does not seem to differentiate Synth from MIDI devices */
> - MODM_NumFMSynthDevs = numsynthdevs;
> - MODM_NumDevs = numsynthdevs + nummididevs;
> -
> - MIDM_NumDevs = nummididevs;
> -
> - /* close file and exit */
> - midiCloseSeq();
> -
> - return 0;
> + return err;
> }
>
> /**************************************************************************
> @@ -363,8 +141,8 @@ static LRESULT OSS_MidiExit(void)
> if (--MIDI_loadcount)
> return 1;
>
> - ZeroMemory(MidiInDev, sizeof(MidiInDev));
> - ZeroMemory(MidiOutDev, sizeof(MidiOutDev));
> + MidiInDev = NULL;
> + MidiOutDev = NULL;
>
> MODM_NumDevs = 0;
> MODM_NumFMSynthDevs = 0;
> diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c
> index b4e2cbda704..4f3c0bcb2cf 100644
> --- a/dlls/wineoss.drv/oss.c
> +++ b/dlls/wineoss.drv/oss.c
> @@ -1405,4 +1405,5 @@ unixlib_entry_t __wine_unix_call_funcs[] =
> set_volumes,
> set_event_handle,
> is_started,
> + midi_init,
> };
> diff --git a/dlls/wineoss.drv/ossmidi.c b/dlls/wineoss.drv/ossmidi.c
> new file mode 100644
> index 00000000000..75fbf6d7bee
> --- /dev/null
> +++ b/dlls/wineoss.drv/ossmidi.c
> @@ -0,0 +1,335 @@
> +/*
> + * MIDI driver for OSS (unixlib)
> + *
> + * Copyright 1994 Martin Ayotte
> + * Copyright 1998 Luiz Otavio L. Zorzella (init procedures)
> + * Copyright 1998, 1999 Eric POUECH
> + * Copyright 2022 Huw Davies
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
> + */
> +
> +#if 0
> +#pragma makedep unix
> +#endif
> +
> +#include "config.h"
> +
> +#include <stdarg.h>
> +#include <string.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <sys/ioctl.h>
> +#include <sys/soundcard.h>
> +
> +#include "ntstatus.h"
> +#define WIN32_NO_STATUS
> +#include "winternl.h"
> +#include "audioclient.h"
> +
> +#include "wine/debug.h"
> +#include "wine/unixlib.h"
> +
> +#include "unixlib.h"
> +
> +static unsigned int num_dests, num_srcs, num_synths, seq_refs;
> +static struct midi_dest dests[MAX_MIDIOUTDRV];
> +static struct midi_src srcs[MAX_MIDIINDRV];
> +
> +WINE_DEFAULT_DEBUG_CHANNEL(midi);
> +
> +static int oss_to_win_device_type(int type)
> +{
> + /* MOD_MIDIPORT output port
> + * MOD_SYNTH generic internal synth
> + * MOD_SQSYNTH square wave internal synth
> + * MOD_FMSYNTH FM internal synth
> + * MOD_MAPPER MIDI mapper
> + * MOD_WAVETABLE hardware wavetable internal synth
> + * MOD_SWSYNTH software internal synth
> + */
> +
> + /* FIXME Is this really the correct equivalence from UNIX to
> + Windows Sound type */
> +
> + switch (type)
> + {
> + case SYNTH_TYPE_FM: return MOD_FMSYNTH;
> + case SYNTH_TYPE_SAMPLE: return MOD_SYNTH;
> + case SYNTH_TYPE_MIDI: return MOD_MIDIPORT;
> + default:
> + ERR("Cannot determine the type of this midi device. "
> + "Assuming FM Synth\n");
> + return MOD_FMSYNTH;
> + }
> +}
> +
> +static int seq_open(void)
> +{
> + static int midi_warn = 1;
> + static int fd = -1;
> +
> + if (seq_refs <= 0)
> + {
> + const char* device = getenv("MIDIDEV");
> +
> + if (!device) device = "/dev/sequencer";
> + fd = open(device, O_RDWR, 0);
> + if (fd == -1)
> + {
> + if (midi_warn)
> + {
> + WARN("Can't open MIDI device '%s' ! (%s). If your program needs this (probably not): %s\n",
> + device, strerror(errno),
> + errno == ENOENT ? "create it ! (\"man MAKEDEV\" ?)" :
> + errno == ENODEV ? "load MIDI sequencer kernel driver !" :
> + errno == EACCES ? "grant access ! (\"man chmod\")" : "");
> + }
> + midi_warn = 0;
> + return -1;
> + }
> + fcntl(fd, F_SETFD, 1); /* set close on exec flag */
> + ioctl(fd, SNDCTL_SEQ_RESET);
> + }
> + seq_refs++;
> + return fd;
> +}
> +
> +static int seq_close(int fd)
> +{
> + if (--seq_refs == 0)
> + close(fd);
> +
> + return 0;
> +}
> +
> +NTSTATUS midi_init(void *args)
> +{
> + struct midi_init_params *params = args;
> + int i, status, synth_devs = 255, midi_devs = 255, fd, len;
> + struct synth_info sinfo;
> + struct midi_info minfo;
> + struct midi_dest *dest;
> + struct midi_src *src;
> +
> + /* try to open device */
> + fd = seq_open();
> + if (fd == -1)
> + {
> + *params->err = -1;
> + return STATUS_SUCCESS;
> + }
> +
> + /* find how many Synth devices are there in the system */
> + status = ioctl(fd, SNDCTL_SEQ_NRSYNTHS, &synth_devs);
> + if (status == -1)
> + {
> + ERR("ioctl for nr synth failed.\n");
> + seq_close(fd);
> + *params->err = -1;
> + return STATUS_SUCCESS;
> + }
> +
> + if (synth_devs > MAX_MIDIOUTDRV)
> + {
> + ERR("MAX_MIDIOUTDRV (%d) was enough for the number of devices (%d). "
> + "Some FM devices will not be available.\n", MAX_MIDIOUTDRV, synth_devs);
> + synth_devs = MAX_MIDIOUTDRV;
> + }
> +
> + for (i = 0, dest = dests; i < synth_devs; i++, dest++)
> + {
> + /* 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.
> + */
> + dest->caps.wMid = 0x00FF;
> + dest->caps.wPid = 0x0001; /* FIXME Product ID */
> + /* Product Version. We simply say "1" */
> + dest->caps.vDriverVersion = 0x001;
> + /* The following are mandatory for MOD_MIDIPORT */
> + dest->caps.wChannelMask = 0xFFFF;
> + dest->caps.wVoices = 0;
> + dest->caps.wNotes = 0;
> + dest->caps.dwSupport = 0;
> +
> + sinfo.device = i;
> + status = ioctl(fd, SNDCTL_SYNTH_INFO, &sinfo);
> + if (status == -1)
> + {
> + char buf[255];
> +
> + ERR("ioctl for synth info failed on %d, disabling it.\n", i);
> +
> + sprintf(buf, "Wine OSS Midi Out #%d disabled", i);
> + len = ntdll_umbstowcs(buf, strlen(buf) + 1, dest->caps.szPname, ARRAY_SIZE(dest->caps.szPname));
> + dest->caps.szPname[len - 1] = '\0';
> + dest->caps.wTechnology = MOD_MIDIPORT;
> + dest->bEnabled = FALSE;
> + }
> + else
> + {
> + len = ntdll_umbstowcs(sinfo.name, strlen(sinfo.name) + 1, dest->caps.szPname, ARRAY_SIZE(dest->caps.szPname));
> + dest->caps.szPname[len - 1] = '\0';
> + dest->caps.wTechnology = oss_to_win_device_type(sinfo.synth_type);
> +
> + if (dest->caps.wTechnology != MOD_MIDIPORT)
> + {
> + /* FIXME Do we have this information?
> + * Assuming the soundcards can handle
> + * MIDICAPS_VOLUME and MIDICAPS_LRVOLUME but
> + * not MIDICAPS_CACHE.
> + */
> + dest->caps.dwSupport = MIDICAPS_VOLUME | MIDICAPS_LRVOLUME;
> + dest->caps.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
> + */
> + dest->caps.wNotes = sinfo.nr_voices;
> + }
> + dest->bEnabled = TRUE;
> +
> + /* We also have the information sinfo.synth_subtype, not used here
> + */
> + if (sinfo.capabilities & SYNTH_CAP_INPUT)
> + FIXME("Synthesizer supports MIDI in. Not yet supported.\n");
> +
> + TRACE("SynthOut[%d]\tOSS info: synth type=%d/%d capa=%lx\n",
> + i, sinfo.synth_type, sinfo.synth_subtype, (long)sinfo.capabilities);
> + }
> +
> + TRACE("SynthOut[%d]\tname='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%d\n",
> + i, wine_dbgstr_w(dest->caps.szPname), dest->caps.wTechnology,
> + dest->caps.wVoices, dest->caps.wNotes, dest->caps.wChannelMask, dest->caps.dwSupport);
> + }
> +
> + /* find how many MIDI devices are there in the system */
> + status = ioctl(fd, SNDCTL_SEQ_NRMIDIS, &midi_devs);
> + if (status == -1)
> + {
> + ERR("ioctl on nr midi failed.\n");
> + midi_devs = 0;
> + goto wrapup;
> + }
> +
> + /* FIXME: the two restrictions below could be loosened in some cases */
> + if (synth_devs + midi_devs > MAX_MIDIOUTDRV)
> + {
> + ERR("MAX_MIDIOUTDRV was not enough for the number of devices. "
> + "Some MIDI devices will not be available.\n");
> + midi_devs = MAX_MIDIOUTDRV - synth_devs;
> + }
> +
> + if (midi_devs > MAX_MIDIINDRV)
> + {
> + ERR("MAX_MIDIINDRV (%d) was not enough for the number of devices (%d). "
> + "Some MIDI devices will not be available.\n", MAX_MIDIINDRV, midi_devs);
> + midi_devs = MAX_MIDIINDRV;
> + }
> +
> + dest = dests + synth_devs;
> + src = srcs;
> + for (i = 0; i < midi_devs; i++, dest++, src++)
> + {
> + minfo.device = i;
> + status = ioctl(fd, SNDCTL_MIDI_INFO, &minfo);
> + if (status == -1) WARN("ioctl on midi info for device %d failed.\n", i);
> +
> + /* Manufacturer 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
> + */
> + dest->caps.wMid = 0x00FF;
> + dest->caps.wPid = 0x0001; /* FIXME Product ID */
> + /* Product Version. We simply say "1" */
> + dest->caps.vDriverVersion = 0x001;
> + if (status == -1)
> + {
> + char buf[255];
> +
> + sprintf(buf, "Wine OSS Midi Out #%d disabled", synth_devs + i);
> + len = ntdll_umbstowcs(buf, strlen(buf) + 1, dest->caps.szPname, ARRAY_SIZE(dest->caps.szPname));
> + dest->caps.szPname[len - 1] = '\0';
> + dest->bEnabled = FALSE;
> + }
> + else
> + {
> + len = ntdll_umbstowcs(minfo.name, strlen(minfo.name) + 1, dest->caps.szPname, ARRAY_SIZE(dest->caps.szPname));
> + dest->caps.szPname[len - 1] = '\0';
> + dest->bEnabled = TRUE;
> + }
> + dest->caps.wTechnology = MOD_MIDIPORT;
> + dest->caps.wVoices = 0;
> + dest->caps.wNotes = 0;
> + dest->caps.wChannelMask = 0xFFFF;
> + dest->caps.dwSupport = 0;
> +
> + /* 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 */
> + src->caps.wMid = 0x00FF;
> + src->caps.wPid = 0x0001; /* FIXME Product ID */
> + /* Product Version. We simply say "1" */
> + src->caps.vDriverVersion = 0x001;
> + if (status == -1)
> + {
> + char buf[ARRAY_SIZE(dest->caps.szPname)];
> +
> + sprintf(buf, "Wine OSS Midi In #%d disabled", synth_devs + i);
> + len = ntdll_umbstowcs(buf, strlen(buf) + 1, src->caps.szPname, ARRAY_SIZE(src->caps.szPname));
> + src->caps.szPname[len - 1] = '\0';
> + src->state = -1;
> + }
> + else
> + {
> + len = ntdll_umbstowcs(minfo.name, strlen(minfo.name) + 1, src->caps.szPname, ARRAY_SIZE(src->caps.szPname));
> + src->caps.szPname[len - 1] = '\0';
> + src->state = 0;
> + }
> + src->caps.dwSupport = 0; /* mandatory with MIDIINCAPS */
> +
> + TRACE("OSS info: midi[%d] dev-type=%d capa=%lx\n"
> + "\tMidiOut[%d] name='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%d\n"
> + "\tMidiIn [%d] name='%s' support=%d\n",
> + i, minfo.dev_type, (long)minfo.capabilities,
> + synth_devs + i, wine_dbgstr_w(dest->caps.szPname), dest->caps.wTechnology,
> + dest->caps.wVoices, dest->caps.wNotes, dest->caps.wChannelMask, dest->caps.dwSupport,
> + i, wine_dbgstr_w(src->caps.szPname), src->caps.dwSupport);
> + }
> +
> +wrapup:
> + /* windows does not seem to differentiate Synth from MIDI devices */
> + num_synths = synth_devs;
> + num_dests = synth_devs + midi_devs;
> + num_srcs = midi_devs;
> +
> + /* close file and exit */
> + seq_close(fd);
> +
> + *params->err = 0;
> + params->num_srcs = num_srcs;
> + params->num_dests = num_dests;
> + params->num_synths = num_synths;
> + params->srcs = srcs;
> + params->dests = dests;
> +
> + return STATUS_SUCCESS;
> +}
> diff --git a/dlls/wineoss.drv/unixlib.h b/dlls/wineoss.drv/unixlib.h
> index 1ed152fe794..2b30c5992c7 100644
> --- a/dlls/wineoss.drv/unixlib.h
> +++ b/dlls/wineoss.drv/unixlib.h
> @@ -209,6 +209,41 @@ struct is_started_params
> HRESULT result;
> };
>
> +#include <mmddk.h> /* temporary */
> +
> +typedef struct midi_src
> +{
> + int state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
> + MIDIOPENDESC midiDesc;
> + WORD wFlags;
> + MIDIHDR *lpQueueHdr;
> + unsigned char incoming[3];
> + unsigned char incPrev;
> + char incLen;
> + UINT startTime;
> + MIDIINCAPSW caps;
> +} WINE_MIDIIN;
> +
> +typedef struct midi_dest
> +{
> + BOOL bEnabled;
> + MIDIOPENDESC midiDesc;
> + WORD wFlags;
> + MIDIHDR *lpQueueHdr;
> + void *lpExtra; /* according to port type (MIDI, FM...), extra data when needed */
> + MIDIOUTCAPSW caps;
> +} WINE_MIDIOUT;
> +
> +struct midi_init_params
> +{
> + UINT *err;
> + unsigned int num_dests;
> + unsigned int num_srcs;
> + unsigned int num_synths;
> + struct midi_dest *dests;
> + struct midi_src *srcs;
> +};
> +
> enum oss_funcs
> {
> oss_test_connect,
> @@ -234,8 +269,11 @@ enum oss_funcs
> oss_set_volumes,
> oss_set_event_handle,
> oss_is_started,
> + oss_midi_init,
> };
>
> +NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
> +
> extern unixlib_handle_t oss_handle;
>
> #define OSS_CALL(func, params) __wine_unix_call(oss_handle, oss_ ## func, params)
> --
> 2.25.1
>
>
More information about the wine-devel
mailing list