From ab31ca4db5b42877806621482b05901d4628d549 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Tue, 9 Nov 2004 14:52:52 +0000 Subject: [PATCH] Move midimap.drv (a 9x component) to midimap.dll (an NT component), make it build with baseaddress.cfg. svn path=/trunk/; revision=11603 --- reactos/lib/midimap/.cvsignore | 11 + reactos/lib/midimap/Makefile.in | 13 + reactos/lib/midimap/Makefile.ros-template | 23 + reactos/lib/midimap/makefile | 9 + reactos/lib/midimap/midimap.c | 555 ++++++++++++++++++++++ reactos/lib/midimap/midimap.rc | 7 + reactos/lib/midimap/midimap.spec | 2 + reactos/lib/midimap/winehq2ros.patch | 0 8 files changed, 620 insertions(+) create mode 100644 reactos/lib/midimap/.cvsignore create mode 100644 reactos/lib/midimap/Makefile.in create mode 100644 reactos/lib/midimap/Makefile.ros-template create mode 100644 reactos/lib/midimap/makefile create mode 100644 reactos/lib/midimap/midimap.c create mode 100644 reactos/lib/midimap/midimap.rc create mode 100644 reactos/lib/midimap/midimap.spec create mode 100644 reactos/lib/midimap/winehq2ros.patch diff --git a/reactos/lib/midimap/.cvsignore b/reactos/lib/midimap/.cvsignore new file mode 100644 index 00000000000..07322b0ef28 --- /dev/null +++ b/reactos/lib/midimap/.cvsignore @@ -0,0 +1,11 @@ +*.a +*.d +*.o +*.dll +*.coff +*.sym +*.map +*.tmp +temp.exp +midimap.spec.def +Makefile.ros diff --git a/reactos/lib/midimap/Makefile.in b/reactos/lib/midimap/Makefile.in new file mode 100644 index 00000000000..35bfeac72c8 --- /dev/null +++ b/reactos/lib/midimap/Makefile.in @@ -0,0 +1,13 @@ +TOPSRCDIR = @top_srcdir@ +TOPOBJDIR = ../../.. +SRCDIR = @srcdir@ +VPATH = @srcdir@ +MODULE = midimap.drv +IMPORTS = winmm user32 advapi32 kernel32 + +C_SRCS = \ + midimap.c + +@MAKE_DLL_RULES@ + +### Dependencies: diff --git a/reactos/lib/midimap/Makefile.ros-template b/reactos/lib/midimap/Makefile.ros-template new file mode 100644 index 00000000000..abeac05dba9 --- /dev/null +++ b/reactos/lib/midimap/Makefile.ros-template @@ -0,0 +1,23 @@ +# $Id: Makefile.ros-template,v 1.1 2004/11/09 14:52:52 ion Exp $ + +TARGET_NAME = midimap + +TARGET_OBJECTS = @C_SRCS@ + +TARGET_CFLAGS = @EXTRADEFS@ -D__REACTOS__ + +TARGET_SDKLIBS = @IMPORTS@ winmm.a libwine.a wine_uuid.a ntdll.a + +TARGET_BASE = $(TARGET_LIB_BASE_MIDIMAP) + +TARGET_RC_SRCS = @RC_SRCS@ +TARGET_RC_BINSRC = @RC_BINSRC@ +TARGET_RC_BINARIES = @RC_BINARIES@ + +TARGET_EXTENSION = .dll + +default: all + +DEP_OBJECTS = $(TARGET_OBJECTS) + +include $(TOOLS_PATH)/depend.mk diff --git a/reactos/lib/midimap/makefile b/reactos/lib/midimap/makefile new file mode 100644 index 00000000000..1814643a68b --- /dev/null +++ b/reactos/lib/midimap/makefile @@ -0,0 +1,9 @@ +# $Id: makefile,v 1.1 2004/11/09 14:52:52 ion Exp $ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = winedll + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/lib/midimap/midimap.c b/reactos/lib/midimap/midimap.c new file mode 100644 index 00000000000..67446c278bc --- /dev/null +++ b/reactos/lib/midimap/midimap.c @@ -0,0 +1,555 @@ +/* -*- tab-width: 8; c-basic-offset: 4 -*- */ +/* + * Wine MIDI mapper driver + * + * Copyright 1999, 2000, 2001 Eric Pouech + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * TODO: + * notification has to be implemented + * IDF file loading + */ + +#include +#include +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "mmddk.h" +#include "winreg.h" +#include "wine/debug.h" + +/* + * Here's how Windows stores the midiOut mapping information. + * + * Full form (in HKU) is: + * + * [Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap] 988836060 + * "AutoScheme"=dword:00000000 + * "ConfigureCount"=dword:00000004 + * "CurrentInstrument"="Wine OSS midi" + * "CurrentScheme"="epp" + * "DriverList"="" + * "UseScheme"=dword:00000000 + * + * AutoScheme: ? + * CurrentInstrument: name of midiOut device to use when UseScheme is 0. Wine uses an extension + * of the form #n to link to n'th midiOut device of the system + * CurrentScheme: when UseScheme is non null, it's the scheme to use (see below) + * DriverList: ? + * UseScheme: trigger for simple/complex mapping + * + * A scheme is defined (in HKLM) as: + * + * [System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Midi\\Schemes\\] + * : one key for each defined scheme (system wide) + * under each one of these keys, there's: + * [...\\\\] + * "Channels"="" + * (the default value of this key also refers to the name of the device). + * + * this defines, for each midiOut device (identified by its index in ), which + * channels have to be mapped onto it. The defines the channels (from 0 to 15) + * will be mapped (mapping occurs for channel if bit is set in + * + * Further mapping information can also be defined in: + * [System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Midi\\Ports\\\\Instruments\\] + * "Definition"="<.idf file>" + * "FriendlyName"="#for .idx file#" + * "Port"="" + * + * This last part isn't implemented (.idf file support). + */ + +WINE_DEFAULT_DEBUG_CHANNEL(msacm); + +typedef struct tagMIDIOUTPORT +{ + char name[MAXPNAMELEN]; + int loaded; + HMIDIOUT hMidi; + unsigned short uDevID; + LPBYTE lpbPatch; + unsigned int aChn[16]; +} MIDIOUTPORT; + +typedef struct tagMIDIMAPDATA +{ + struct tagMIDIMAPDATA* self; + MIDIOUTPORT* ChannelMap[16]; +} MIDIMAPDATA; + +static MIDIOUTPORT* midiOutPorts; +static unsigned numMidiOutPorts; + +static BOOL MIDIMAP_IsBadData(MIDIMAPDATA* mm) +{ + if (!IsBadReadPtr(mm, sizeof(MIDIMAPDATA)) && mm->self == mm) + return FALSE; + TRACE("Bad midimap data (%p)\n", mm); + return TRUE; +} + +static BOOL MIDIMAP_FindPort(const char* name, unsigned* dev) +{ + for (*dev = 0; *dev < numMidiOutPorts; (*dev)++) + { + TRACE("%s\n", midiOutPorts[*dev].name); + if (strcmp(midiOutPorts[*dev].name, name) == 0) + return TRUE; + } + /* try the form #nnn */ + if (*name == '#' && isdigit(name[1])) + { + *dev = atoi(name + 1); + if (*dev < numMidiOutPorts) + return TRUE; + } + return FALSE; +} + +static BOOL MIDIMAP_LoadSettingsDefault(MIDIMAPDATA* mom, const char* port) +{ + unsigned i, dev = 0; + + if (port != NULL && !MIDIMAP_FindPort(port, &dev)) + { + ERR("Registry glitch: couldn't find midi out (%s)\n", port); + dev = 0; + } + + /* this is necessary when no midi out ports are present */ + if (dev >= numMidiOutPorts) + return FALSE; + /* sets default */ + for (i = 0; i < 16; i++) mom->ChannelMap[i] = &midiOutPorts[dev]; + + return TRUE; +} + +static BOOL MIDIMAP_LoadSettingsScheme(MIDIMAPDATA* mom, const char* scheme) +{ + HKEY hSchemesKey, hKey, hPortKey; + unsigned i, idx, dev; + char buffer[256], port[256]; + DWORD type, size, mask; + + for (i = 0; i < 16; i++) mom->ChannelMap[i] = NULL; + + if (RegOpenKeyA(HKEY_LOCAL_MACHINE, + "System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Midi\\Schemes", + &hSchemesKey)) + { + return FALSE; + } + if (RegOpenKeyA(hSchemesKey, scheme, &hKey)) + { + RegCloseKey(hSchemesKey); + return FALSE; + } + + for (idx = 0; !RegEnumKeyA(hKey, idx, buffer, sizeof(buffer)); idx++) + { + if (RegOpenKeyA(hKey, buffer, &hPortKey)) continue; + + size = sizeof(port); + if (RegQueryValueExA(hPortKey, NULL, 0, &type, port, &size)) continue; + + if (!MIDIMAP_FindPort(port, &dev)) continue; + + size = sizeof(mask); + if (RegQueryValueExA(hPortKey, "Channels", 0, &type, (void*)&mask, &size)) + continue; + + for (i = 0; i < 16; i++) + { + if (mask & (1 << i)) + { + if (mom->ChannelMap[i]) + ERR("Quirks in registry, channel %u is mapped twice\n", i); + mom->ChannelMap[i] = &midiOutPorts[dev]; + } + } + } + + RegCloseKey(hSchemesKey); + RegCloseKey(hKey); + + return TRUE; +} + +static BOOL MIDIMAP_LoadSettings(MIDIMAPDATA* mom) +{ + HKEY hKey; + BOOL ret; + + if (RegOpenKeyA(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Multimedia\\MIDIMap", &hKey)) + { + ret = MIDIMAP_LoadSettingsDefault(mom, NULL); + } + else + { + DWORD type, size, out; + char buffer[256]; + + ret = 2; + size = sizeof(out); + if (!RegQueryValueExA(hKey, "UseScheme", 0, &type, (void*)&out, &size) && out) + { + size = sizeof(buffer); + if (!RegQueryValueExA(hKey, "CurrentScheme", 0, &type, buffer, &size)) + { + if (!(ret = MIDIMAP_LoadSettingsScheme(mom, buffer))) + ret = MIDIMAP_LoadSettingsDefault(mom, NULL); + } + else + { + ERR("Wrong registry: UseScheme is active, but no CurrentScheme found\n"); + } + } + if (ret == 2) + { + size = sizeof(buffer); + if (!RegQueryValueExA(hKey, "CurrentInstrument", 0, &type, buffer, &size) && *buffer) + { + ret = MIDIMAP_LoadSettingsDefault(mom, buffer); + } + else + { + ret = MIDIMAP_LoadSettingsDefault(mom, NULL); + } + } + } + RegCloseKey(hKey); + + if (ret && TRACE_ON(msacm)) + { + unsigned i; + + for (i = 0; i < 16; i++) + { + TRACE("chnMap[%2d] => %d\n", + i, mom->ChannelMap[i] ? mom->ChannelMap[i]->uDevID : -1); + } + } + return ret; +} + +static DWORD modOpen(LPDWORD lpdwUser, LPMIDIOPENDESC lpDesc, DWORD dwFlags) +{ + MIDIMAPDATA* mom = HeapAlloc(GetProcessHeap(), 0, sizeof(MIDIMAPDATA)); + + TRACE("(%p %p %08lx)\n", lpdwUser, lpDesc, dwFlags); + + if (!mom) return MMSYSERR_NOMEM; + + if (MIDIMAP_LoadSettings(mom)) + { + *lpdwUser = (DWORD)mom; + mom->self = mom; + + return MMSYSERR_NOERROR; + } + HeapFree(GetProcessHeap(), 0, mom); + return MIDIERR_INVALIDSETUP; +} + +static DWORD modClose(MIDIMAPDATA* mom) +{ + UINT i; + DWORD ret = MMSYSERR_NOERROR; + + if (MIDIMAP_IsBadData(mom)) return MMSYSERR_ERROR; + + for (i = 0; i < 16; i++) + { + DWORD t; + if (mom->ChannelMap[i] && mom->ChannelMap[i]->loaded > 0) + { + t = midiOutClose(mom->ChannelMap[i]->hMidi); + if (t == MMSYSERR_NOERROR) + { + mom->ChannelMap[i]->loaded = 0; + mom->ChannelMap[i]->hMidi = 0; + } + else if (ret == MMSYSERR_NOERROR) + ret = t; + } + } + if (ret == MMSYSERR_NOERROR) + HeapFree(GetProcessHeap(), 0, mom); + return ret; +} + +static DWORD modLongData(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2) +{ + WORD chn; + DWORD ret = MMSYSERR_NOERROR; + MIDIHDR mh; + + if (MIDIMAP_IsBadData(mom)) + return MMSYSERR_ERROR; + + mh = *lpMidiHdr; + for (chn = 0; chn < 16; chn++) + { + if (mom->ChannelMap[chn] && mom->ChannelMap[chn]->loaded > 0) + { + mh.dwFlags = 0; + midiOutPrepareHeader(mom->ChannelMap[chn]->hMidi, &mh, sizeof(mh)); + ret = midiOutLongMsg(mom->ChannelMap[chn]->hMidi, &mh, sizeof(mh)); + midiOutUnprepareHeader(mom->ChannelMap[chn]->hMidi, &mh, sizeof(mh)); + if (ret != MMSYSERR_NOERROR) break; + } + } + return ret; +} + +static DWORD modData(MIDIMAPDATA* mom, DWORD dwParam) +{ + BYTE lb = LOBYTE(LOWORD(dwParam)); + WORD chn = lb & 0x0F; + DWORD ret = MMSYSERR_NOERROR; + + if (MIDIMAP_IsBadData(mom)) + return MMSYSERR_ERROR; + + if (!mom->ChannelMap[chn]) return MMSYSERR_NOERROR; + + switch (lb & 0xF0) + { + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + case 0xC0: + case 0xD0: + case 0xE0: + if (mom->ChannelMap[chn]->loaded == 0) + { + if (midiOutOpen(&mom->ChannelMap[chn]->hMidi, mom->ChannelMap[chn]->uDevID, + 0L, 0L, CALLBACK_NULL) == MMSYSERR_NOERROR) + mom->ChannelMap[chn]->loaded = 1; + else + mom->ChannelMap[chn]->loaded = -1; + /* FIXME: should load here the IDF midi data... and allow channel and + * patch mappings + */ + } + if (mom->ChannelMap[chn]->loaded > 0) + { + /* change channel */ + dwParam &= ~0x0F; + dwParam |= mom->ChannelMap[chn]->aChn[chn]; + + if ((LOBYTE(LOWORD(dwParam)) & 0xF0) == 0xC0 /* program change */ && + mom->ChannelMap[chn]->lpbPatch) + { + BYTE patch = HIBYTE(LOWORD(dwParam)); + + /* change patch */ + dwParam &= ~0x0000FF00; + dwParam |= mom->ChannelMap[chn]->lpbPatch[patch]; + } + ret = midiOutShortMsg(mom->ChannelMap[chn]->hMidi, dwParam); + } + break; + case 0xF0: + for (chn = 0; chn < 16; chn++) + { + if (mom->ChannelMap[chn]->loaded > 0) + ret = midiOutShortMsg(mom->ChannelMap[chn]->hMidi, dwParam); + } + break; + default: + FIXME("ooch %lu\n", dwParam); + } + + return ret; +} + +static DWORD modPrepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2) +{ + if (MIDIMAP_IsBadData(mom)) return MMSYSERR_ERROR; + if (lpMidiHdr->dwFlags & (MHDR_ISSTRM|MHDR_PREPARED)) + return MMSYSERR_INVALPARAM; + + lpMidiHdr->dwFlags |= MHDR_PREPARED; + return MMSYSERR_NOERROR; +} + +static DWORD modUnprepare(MIDIMAPDATA* mom, LPMIDIHDR lpMidiHdr, DWORD dwParam2) +{ + if (MIDIMAP_IsBadData(mom)) return MMSYSERR_ERROR; + if ((lpMidiHdr->dwFlags & MHDR_ISSTRM) || !(lpMidiHdr->dwFlags & MHDR_PREPARED)) + return MMSYSERR_INVALPARAM; + + lpMidiHdr->dwFlags &= ~MHDR_PREPARED; + return MMSYSERR_NOERROR; +} + +static DWORD modGetDevCaps(UINT wDevID, MIDIMAPDATA* mom, LPMIDIOUTCAPSA lpMidiCaps, DWORD size) +{ + lpMidiCaps->wMid = 0x00FF; + lpMidiCaps->wPid = 0x0001; + lpMidiCaps->vDriverVersion = 0x0100; + strcpy(lpMidiCaps->szPname, "Wine midi out mapper"); + lpMidiCaps->wTechnology = MOD_MAPPER; + lpMidiCaps->wVoices = 0; + lpMidiCaps->wNotes = 0; + lpMidiCaps->wChannelMask = 0xFFFF; + lpMidiCaps->dwSupport = 0L; + + return MMSYSERR_NOERROR; +} + +static DWORD modReset(MIDIMAPDATA* mom) +{ + WORD chn; + DWORD ret = MMSYSERR_NOERROR; + + if (MIDIMAP_IsBadData(mom)) + return MMSYSERR_ERROR; + + for (chn = 0; chn < 16; chn++) + { + if (mom->ChannelMap[chn] && mom->ChannelMap[chn]->loaded > 0) + { + ret = midiOutReset(mom->ChannelMap[chn]->hMidi); + if (ret != MMSYSERR_NOERROR) break; + } + } + return ret; +} + +/************************************************************************** + * modMessage (MIDIMAP.@) + */ +DWORD WINAPI MIDIMAP_modMessage(UINT wDevID, UINT wMsg, DWORD dwUser, + DWORD dwParam1, DWORD dwParam2) +{ + TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n", + wDevID, wMsg, dwUser, dwParam1, dwParam2); + + switch (wMsg) + { + case DRVM_INIT: + case DRVM_EXIT: + case DRVM_ENABLE: + case DRVM_DISABLE: + /* FIXME: Pretend this is supported */ + return 0; + + case MODM_OPEN: return modOpen ((LPDWORD)dwUser, (LPMIDIOPENDESC)dwParam1,dwParam2); + case MODM_CLOSE: return modClose ((MIDIMAPDATA*)dwUser); + + case MODM_DATA: return modData ((MIDIMAPDATA*)dwUser, dwParam1); + case MODM_LONGDATA: return modLongData ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2); + case MODM_PREPARE: return modPrepare ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2); + case MODM_UNPREPARE: return modUnprepare ((MIDIMAPDATA*)dwUser, (LPMIDIHDR)dwParam1, dwParam2); + case MODM_RESET: return modReset ((MIDIMAPDATA*)dwUser); + + case MODM_GETDEVCAPS: return modGetDevCaps (wDevID, (MIDIMAPDATA*)dwUser, (LPMIDIOUTCAPSA)dwParam1,dwParam2); + case MODM_GETNUMDEVS: return 1; + case MODM_GETVOLUME: return MMSYSERR_NOTSUPPORTED; + case MODM_SETVOLUME: return MMSYSERR_NOTSUPPORTED; + default: + FIXME("unknown message %d!\n", wMsg); + } + return MMSYSERR_NOTSUPPORTED; +} + +/*======================================================================* + * Driver part * + *======================================================================*/ + +/************************************************************************** + * MIDIMAP_drvOpen [internal] + */ +static DWORD MIDIMAP_drvOpen(LPSTR str) +{ + MIDIOUTCAPSA moc; + unsigned dev, i; + + if (midiOutPorts) + return 0; + + numMidiOutPorts = midiOutGetNumDevs(); + midiOutPorts = HeapAlloc(GetProcessHeap(), 0, + numMidiOutPorts * sizeof(MIDIOUTPORT)); + for (dev = 0; dev < numMidiOutPorts; dev++) + { + if (midiOutGetDevCapsA(dev, &moc, sizeof(moc)) == 0L) + { + strcpy(midiOutPorts[dev].name, moc.szPname); + midiOutPorts[dev].loaded = 0; + midiOutPorts[dev].hMidi = 0; + midiOutPorts[dev].uDevID = dev; + midiOutPorts[dev].lpbPatch = NULL; + for (i = 0; i < 16; i++) + midiOutPorts[dev].aChn[i] = i; + } + else + { + midiOutPorts[dev].loaded = -1; + } + } + + return 1; +} + +/************************************************************************** + * MIDIMAP_drvClose [internal] + */ +static DWORD MIDIMAP_drvClose(DWORD dwDevID) +{ + if (midiOutPorts) + { + HeapFree(GetProcessHeap(), 0, midiOutPorts); + midiOutPorts = NULL; + return 1; + } + return 0; +} + +/************************************************************************** + * DriverProc (MIDIMAP.@) + */ +LONG CALLBACK MIDIMAP_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg, + DWORD dwParam1, DWORD dwParam2) +{ +/* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */ +/* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */ + + switch (wMsg) + { + case DRV_LOAD: return 1; + case DRV_FREE: return 1; + case DRV_OPEN: return MIDIMAP_drvOpen((LPSTR)dwParam1); + case DRV_CLOSE: return MIDIMAP_drvClose(dwDevID); + case DRV_ENABLE: return 1; + case DRV_DISABLE: return 1; + case DRV_QUERYCONFIGURE: return 1; + case DRV_CONFIGURE: MessageBoxA(0, "MIDIMAP MultiMedia Driver !", "OSS Driver", MB_OK); return 1; + case DRV_INSTALL: return DRVCNF_RESTART; + case DRV_REMOVE: return DRVCNF_RESTART; + default: + return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2); + } +} diff --git a/reactos/lib/midimap/midimap.rc b/reactos/lib/midimap/midimap.rc new file mode 100644 index 00000000000..32d76e28974 --- /dev/null +++ b/reactos/lib/midimap/midimap.rc @@ -0,0 +1,7 @@ +/* $Id: midimap.rc,v 1.1 2004/11/09 14:52:52 ion Exp $ */ + +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS/WINE MIDI Mapper\0" +#define REACTOS_STR_INTERNAL_NAME "midimap\0" +#define REACTOS_STR_ORIGINAL_FILENAME "midimap.drv\0" +#include diff --git a/reactos/lib/midimap/midimap.spec b/reactos/lib/midimap/midimap.spec new file mode 100644 index 00000000000..e83446b9187 --- /dev/null +++ b/reactos/lib/midimap/midimap.spec @@ -0,0 +1,2 @@ +@ stdcall DriverProc(long long long long long) MIDIMAP_DriverProc +@ stdcall modMessage(long long long long long) MIDIMAP_modMessage diff --git a/reactos/lib/midimap/winehq2ros.patch b/reactos/lib/midimap/winehq2ros.patch new file mode 100644 index 00000000000..e69de29bb2d