Signed-off-by: Huw Davies <huw(a)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