[PATCH 3/3] wineoss: Move midi_init to the unixlib.

Huw Davies huw at codeweavers.com
Tue Apr 19 01:38:44 CDT 2022


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, &params);
 
-    /* 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