Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
beea6151
Commit
beea6151
authored
May 22, 2001
by
Eric Pouech
Committed by
Alexandre Julliard
May 22, 2001
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Made midi mapper more robust.
Added channel to device/channel mapping. Removed midiIn mapping (it doesn't exist on Windows).
parent
d80b4337
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
404 additions
and
184 deletions
+404
-184
midimap.c
dlls/winmm/midimap/midimap.c
+393
-183
midimap.drv.spec
dlls/winmm/midimap/midimap.drv.spec
+1
-1
winedefault.reg
winedefault.reg
+10
-0
No files found.
dlls/winmm/midimap/midimap.c
View file @
beea6151
...
...
@@ -2,250 +2,435 @@
/*
* Wine Midi mapper driver
*
* Copyright 1999 Eric Pouech
* Copyright 1999, 2000, 2001 Eric Pouech
*
* TODO:
* notification has to be implemented
* IDF file loading
*/
#include <string.h>
#include <stdlib.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "mmddk.h"
#include "winreg.h"
#include "debugtools.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\\<nameScheme>]
* <nameScheme>: one key for each defined scheme (system wide)
* under each one of these <nameScheme> keys, there's:
* [...\\<nameScheme>\\<idxDevice>]
* "Channels"="<bitMask>"
* (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 <idxDevice>), which
* channels have to be mapped onto it. The <bitMask> defines the channels (from 0 to 15)
* will be mapped (mapping occurs for channel <ch> if bit <ch> is set in <bitMask>
*
* Further mapping information can also be defined in:
* [System\\CurrentControlSet\\Control\\MediaProperties\\PrivateProperties\\Midi\\Ports\\<nameDevice>\\Instruments\\<idx>]
* "Definition"="<.idf file>"
* "FriendlyName"="#for .idx file#"
* "Port"="<idxPort>"
*
* This last part isn't implemented (.idf file support).
*/
DEFAULT_DEBUG_CHANNEL
(
msacm
);
typedef
struct
tagMIDIMAPDATA
{
typedef
struct
tagMIDIOUTPORT
{
char
name
[
MAXPNAMELEN
];
int
loaded
;
HMIDI
hMidi
;
unsigned
short
uDevID
;
LPBYTE
lpbPatch
;
unsigned
int
aChn
[
16
];
}
MIDIOUTPORT
;
typedef
struct
tagMIDIMAPDATA
{
struct
tagMIDIMAPDATA
*
self
;
HMIDI
hMidi
;
MIDIOUTPORT
*
ChannelMap
[
16
]
;
}
MIDIMAPDATA
;
static
BOOL
MIDIMAP_IsData
(
MIDIMAPDATA
*
mm
)
static
MIDIOUTPORT
*
midiOutPorts
;
static
unsigned
numMidiOutPorts
;
static
BOOL
MIDIMAP_IsBadData
(
MIDIMAPDATA
*
mm
)
{
return
(
!
IsBadReadPtr
(
mm
,
sizeof
(
MIDIMAPDATA
))
&&
mm
->
self
==
mm
);
if
(
!
IsBadReadPtr
(
mm
,
sizeof
(
MIDIMAPDATA
))
&&
mm
->
self
==
mm
)
return
FALSE
;
TRACE
(
"Bad midimap data (%p)
\n
"
,
mm
);
return
TRUE
;
}
/*======================================================================*
* MIDI OUT part *
*======================================================================*/
static
DWORD
modOpen
(
LPDWORD
lpdwUser
,
LPMIDIOPENDESC
lpDesc
,
DWORD
dwFlags
)
static
BOOL
MIDIMAP_FindPort
(
const
char
*
name
,
unsigned
*
dev
)
{
UINT
nd
=
midiOutGetNumDevs
();
UINT
i
;
MIDIMAPDATA
*
mom
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
MIDIMAPDATA
));
TRACE
(
"(%p %p %08lx
\n
"
,
lpdwUser
,
lpDesc
,
dwFlags
);
for
(
i
=
0
;
i
<
nd
;
i
++
)
{
if
(
midiOutOpen
(
&
mom
->
hMidi
,
i
,
lpDesc
->
dwCallback
,
lpDesc
->
dwInstance
,
dwFlags
)
==
MMSYSERR_NOERROR
)
{
lpDesc
->
hMidi
=
mom
->
hMidi
;
*
lpdwUser
=
(
DWORD
)
mom
;
return
MMSYSERR_NOERROR
;
}
for
(
*
dev
=
0
;
*
dev
<
numMidiOutPorts
;
(
*
dev
)
++
)
{
TRACE
(
"%s
\n
"
,
midiOutPorts
[
*
dev
].
name
);
if
(
strcmp
(
midiOutPorts
[
*
dev
].
name
,
name
)
==
0
)
return
TRUE
;
}
HeapFree
(
GetProcessHeap
(),
0
,
mom
);
return
MMSYSERR_ALLOCATED
;
/* try the form #nnn */
if
(
*
name
==
'#'
&&
isdigit
(
name
[
1
]))
{
*
dev
=
atoi
(
name
+
1
);
if
(
*
dev
<
numMidiOutPorts
)
return
TRUE
;
}
return
FALSE
;
}
static
DWORD
modClose
(
MIDIMAPDATA
*
mom
)
static
BOOL
MIDIMAP_LoadSettingsDefault
(
MIDIMAPDATA
*
mom
,
const
char
*
port
)
{
DWORD
ret
=
midiOutClose
(
mom
->
hMidi
);
if
(
ret
==
MMSYSERR_NOERROR
)
HeapFree
(
GetProcessHeap
(),
0
,
mom
);
return
ret
;
}
unsigned
i
,
dev
=
0
;
static
DWORD
modLongData
(
MIDIMAPDATA
*
mom
,
LPMIDIHDR
lpMidiHdr
,
DWORD
dwParam2
)
{
return
midiOutLongMsg
(
mom
->
hMidi
,
lpMidiHdr
,
dwParam2
);
}
if
(
port
!=
NULL
&&
!
MIDIMAP_FindPort
(
port
,
&
dev
))
{
ERR
(
"Registry glitch: couldn't find midi out (%s)
\n
"
,
port
);
dev
=
0
;
}
/* sets default */
for
(
i
=
0
;
i
<
16
;
i
++
)
mom
->
ChannelMap
[
i
]
=
&
midiOutPorts
[
dev
];
static
DWORD
modData
(
MIDIMAPDATA
*
mom
,
DWORD
dwParam
)
{
return
midiOutShortMsg
(
mom
->
hMidi
,
dwParam
);
return
TRUE
;
}
static
DWORD
modPrepare
(
MIDIMAPDATA
*
mom
,
LPMIDIHDR
lpMidiHdr
,
DWORD
dwParam2
)
static
BOOL
MIDIMAP_LoadSettingsScheme
(
MIDIMAPDATA
*
mom
,
const
char
*
scheme
)
{
return
midiOutPrepareHeader
(
mom
->
hMidi
,
lpMidiHdr
,
dwParam2
);
}
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
;
}
static
DWORD
modUnprepare
(
MIDIMAPDATA
*
mom
,
LPMIDIHDR
lpMidiHdr
,
DWORD
dwParam2
)
{
return
midiOutUnprepareHeader
(
mom
->
hMidi
,
lpMidiHdr
,
dwParam2
);
}
for
(
idx
=
0
;
!
RegEnumKeyA
(
hKey
,
idx
,
buffer
,
sizeof
(
buffer
));
idx
++
)
{
if
(
RegOpenKeyA
(
hKey
,
buffer
,
&
hPortKey
))
continue
;
static
DWORD
modGetDevCaps
(
UINT
wDevID
,
MIDIMAPDATA
*
mom
,
LPMIDIOUTCAPSA
lpMidiCaps
,
DWORD
dwParam2
)
{
/* if opened low driver, forward message */
if
(
MIDIMAP_IsData
(
mom
))
return
midiOutGetDevCapsA
(
mom
->
hMidi
,
lpMidiCaps
,
dwParam2
);
/* otherwise, return caps of mapper itself */
if
(
wDevID
==
(
UINT
)
-
1
||
wDevID
==
(
UINT16
)
-
1
)
{
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
=
MIDICAPS_LRVOLUME
|
MIDICAPS_VOLUME
;
size
=
sizeof
(
port
);
if
(
RegQueryValueExA
(
hPortKey
,
NULL
,
0
,
&
type
,
port
,
&
size
))
continue
;
return
MMSYSERR_NOERROR
;
}
ERR
(
"This shouldn't happen
\n
"
);
return
MMSYSERR_ERROR
;
}
if
(
!
MIDIMAP_FindPort
(
port
,
&
dev
))
continue
;
static
DWORD
modGetVolume
(
UINT
wDevID
,
MIDIMAPDATA
*
mom
,
LPDWORD
lpVol
)
{
if
(
MIDIMAP_IsData
(
mom
))
return
midiOutGetVolume
(
mom
->
hMidi
,
lpVol
);
return
MMSYSERR_ERROR
;
}
size
=
sizeof
(
mask
);
if
(
RegQueryValueExA
(
hPortKey
,
"Channels"
,
0
,
&
type
,
(
void
*
)
&
mask
,
&
size
))
continue
;
static
DWORD
modSetVolume
(
UINT
wDevID
,
MIDIMAPDATA
*
mom
,
DWORD
vol
)
{
if
(
MIDIMAP_IsData
(
mom
))
return
midiOutSetVolume
(
mom
->
hMidi
,
vol
);
return
MMSYSERR_ERROR
;
}
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
];
}
}
}
static
DWORD
modReset
(
MIDIMAPDATA
*
mom
)
{
return
midiOutReset
(
mom
->
hMidi
);
RegCloseKey
(
hSchemesKey
);
RegCloseKey
(
hKey
);
return
TRUE
;
}
/**************************************************************************
* MIDIMAP_modMessage [sample driver]
*/
DWORD
WINAPI
MIDIMAP_modMessage
(
UINT
wDevID
,
UINT
wMsg
,
DWORD
dwUser
,
DWORD
dwParam1
,
DWORD
dwParam2
)
static
BOOL
MIDIMAP_LoadSettings
(
MIDIMAPDATA
*
mom
)
{
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
;
HKEY
hKey
;
BOOL
ret
;
case
MODM_OPEN
:
return
modOpen
((
LPDWORD
)
dwUser
,
(
LPMIDIOPENDESC
)
dwParam1
,
dwParam2
);
case
MODM_CLOSE
:
return
modClose
((
MIDIMAPDATA
*
)
dwUser
);
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
);
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
);
if
(
TRACE_ON
(
msacm
))
{
unsigned
i
;
case
MODM_GETDEVCAPS
:
return
modGetDevCaps
(
wDevID
,
(
MIDIMAPDATA
*
)
dwUser
,
(
LPMIDIOUTCAPSA
)
dwParam1
,
dwParam2
);
case
MODM_GETNUMDEVS
:
return
1
;
case
MODM_GETVOLUME
:
return
modGetVolume
(
wDevID
,
(
MIDIMAPDATA
*
)
dwUser
,
(
LPDWORD
)
dwParam1
);
case
MODM_SETVOLUME
:
return
modSetVolume
(
wDevID
,
(
MIDIMAPDATA
*
)
dwUser
,
dwParam1
);
case
MODM_RESET
:
return
modReset
((
MIDIMAPDATA
*
)
dwUser
);
default:
FIXME
(
"unknown message %d!
\n
"
,
wMsg
);
for
(
i
=
0
;
i
<
16
;
i
++
)
{
TRACE
(
"chnMap[% 2d] => %d
\n
"
,
i
,
mom
->
ChannelMap
[
i
]
?
mom
->
ChannelMap
[
i
]
->
uDevID
:
-
1
);
}
}
return
MMSYSERR_NOTSUPPORTED
;
return
ret
;
}
/*======================================================================*
* MIDI IN part *
*======================================================================*/
static
DWORD
midOpen
(
LPDWORD
lpdwUser
,
LPMIDIOPENDESC
lpDesc
,
DWORD
dwFlags
)
static
DWORD
modOpen
(
LPDWORD
lpdwUser
,
LPMIDIOPENDESC
lpDesc
,
DWORD
dwFlags
)
{
UINT
nd
=
midiInGetNumDevs
();
UINT
i
;
MIDIMAPDATA
*
mim
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
MIDIMAPDATA
));
MIDIMAPDATA
*
mom
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
MIDIMAPDATA
));
TRACE
(
"(%p %p %08lx
\n
"
,
lpdwUser
,
lpDesc
,
dwFlags
);
for
(
i
=
0
;
i
<
nd
;
i
++
)
{
if
(
midiInOpen
(
&
mim
->
hMidi
,
i
,
lpDesc
->
dwCallback
,
lpDesc
->
dwInstance
,
dwFlags
)
==
MMSYSERR_NOERROR
)
{
lpDesc
->
hMidi
=
mim
->
hMidi
;
*
lpdwUser
=
(
DWORD
)
mim
;
return
MMSYSERR_NOERROR
;
}
if
(
!
mom
)
return
MMSYSERR_NOMEM
;
if
(
MIDIMAP_LoadSettings
(
mom
))
{
*
lpdwUser
=
(
DWORD
)
mom
;
mom
->
self
=
mom
;
return
MMSYSERR_NOERROR
;
}
HeapFree
(
GetProcessHeap
(),
0
,
m
i
m
);
return
M
MSYSERR_ALLOCATED
;
HeapFree
(
GetProcessHeap
(),
0
,
m
o
m
);
return
M
IDIERR_INVALIDSETUP
;
}
static
DWORD
m
idClose
(
MIDIMAPDATA
*
mi
m
)
static
DWORD
m
odClose
(
MIDIMAPDATA
*
mo
m
)
{
DWORD
ret
=
midiInClose
(
mim
->
hMidi
);
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
,
m
i
m
);
HeapFree
(
GetProcessHeap
(),
0
,
m
o
m
);
return
ret
;
}
static
DWORD
m
idAddBuffer
(
MIDIMAPDATA
*
mi
m
,
LPMIDIHDR
lpMidiHdr
,
DWORD
dwParam2
)
static
DWORD
m
odLongData
(
MIDIMAPDATA
*
mo
m
,
LPMIDIHDR
lpMidiHdr
,
DWORD
dwParam2
)
{
return
midiInAddBuffer
(
mim
->
hMidi
,
lpMidiHdr
,
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
m
idPrepare
(
MIDIMAPDATA
*
mim
,
LPMIDIHDR
lpMidiHdr
,
DWORD
dwParam2
)
static
DWORD
m
odData
(
MIDIMAPDATA
*
mom
,
DWORD
dwParam
)
{
return
midiInPrepareHeader
(
mim
->
hMidi
,
lpMidiHdr
,
dwParam2
);
}
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
);
}
static
DWORD
midUnprepare
(
MIDIMAPDATA
*
mim
,
LPMIDIHDR
lpMidiHdr
,
DWORD
dwParam2
)
{
return
midiInUnprepareHeader
(
mim
->
hMidi
,
lpMidiHdr
,
dwParam2
);
return
ret
;
}
static
DWORD
m
idGetDevCaps
(
UINT
wDevID
,
MIDIMAPDATA
*
mim
,
LPMIDIINCAPSA
lpMidiCaps
,
DWORD
dwParam2
)
static
DWORD
m
odPrepare
(
MIDIMAPDATA
*
mom
,
LPMIDIHDR
lpMidiHdr
,
DWORD
dwParam2
)
{
/* if opened low driver, forward message */
if
(
MIDIMAP_IsData
(
mim
))
return
midiInGetDevCapsA
(
mim
->
hMidi
,
lpMidiCaps
,
dwParam2
);
/* otherwise, return caps of mapper itself */
if
(
wDevID
==
(
UINT
)
-
1
||
wDevID
==
(
UINT16
)
-
1
)
{
lpMidiCaps
->
wMid
=
0x00FF
;
lpMidiCaps
->
wPid
=
0x0001
;
lpMidiCaps
->
vDriverVersion
=
0x0100
;
strcpy
(
lpMidiCaps
->
szPname
,
"Wine midi int mapper"
);
lpMidiCaps
->
dwSupport
=
0
;
if
(
MIDIMAP_IsBadData
(
mom
))
return
MMSYSERR_ERROR
;
if
(
lpMidiHdr
->
dwFlags
&
(
MHDR_ISSTRM
|
MHDR_PREPARED
))
return
MMSYSERR_INVALPARAM
;
return
MMSYSERR_NOERROR
;
}
ERR
(
"This shouldn't happen
\n
"
);
return
MMSYSERR_ERROR
;
lpMidiHdr
->
dwFlags
|=
MHDR_PREPARED
;
return
MMSYSERR_NOERROR
;
}
static
DWORD
m
idStop
(
MIDIMAPDATA
*
mim
)
static
DWORD
m
odUnprepare
(
MIDIMAPDATA
*
mom
,
LPMIDIHDR
lpMidiHdr
,
DWORD
dwParam2
)
{
return
midiInStop
(
mim
->
hMidi
);
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
m
idStart
(
MIDIMAPDATA
*
mim
)
static
DWORD
m
odGetDevCaps
(
UINT
wDevID
,
MIDIMAPDATA
*
mom
,
LPMIDIOUTCAPSA
lpMidiCaps
,
DWORD
size
)
{
return
midiInStart
(
mim
->
hMidi
);
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
m
idReset
(
MIDIMAPDATA
*
mi
m
)
static
DWORD
m
odReset
(
MIDIMAPDATA
*
mo
m
)
{
return
midiInReset
(
mim
->
hMidi
);
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
;
}
/**************************************************************************
* MIDIMAP_m
i
dMessage [sample driver]
* MIDIMAP_m
o
dMessage [sample driver]
*/
DWORD
WINAPI
MIDIMAP_m
idMessage
(
WORD
wDevID
,
WORD
wMsg
,
DWORD
dwUser
,
DWORD
WINAPI
MIDIMAP_m
odMessage
(
UINT
wDevID
,
UINT
wMsg
,
DWORD
dwUser
,
DWORD
dwParam1
,
DWORD
dwParam2
)
{
TRACE
(
"(%u, %04X, %08lX, %08lX, %08lX);
\n
"
,
wDevID
,
wMsg
,
dwUser
,
dwParam1
,
dwParam2
);
switch
(
wMsg
)
{
switch
(
wMsg
)
{
case
DRVM_INIT
:
case
DRVM_EXIT
:
case
DRVM_ENABLE
:
...
...
@@ -253,19 +438,21 @@ DWORD WINAPI MIDIMAP_midMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
/* FIXME: Pretend this is supported */
return
0
;
case
MIDM_OPEN
:
return
midOpen
((
LPDWORD
)
dwUser
,
(
LPMIDIOPENDESC
)
dwParam1
,
dwParam2
);
case
MIDM_CLOSE
:
return
midClose
((
MIDIMAPDATA
*
)
dwUser
);
case
MIDM_ADDBUFFER
:
return
midAddBuffer
((
MIDIMAPDATA
*
)
dwUser
,
(
LPMIDIHDR
)
dwParam1
,
dwParam2
);
case
MIDM_PREPARE
:
return
midPrepare
((
MIDIMAPDATA
*
)
dwUser
,
(
LPMIDIHDR
)
dwParam1
,
dwParam2
);
case
MIDM_UNPREPARE
:
return
midUnprepare
((
MIDIMAPDATA
*
)
dwUser
,
(
LPMIDIHDR
)
dwParam1
,
dwParam2
);
case
MIDM_GETDEVCAPS
:
return
midGetDevCaps
(
wDevID
,
(
MIDIMAPDATA
*
)
dwUser
,
(
LPMIDIINCAPSA
)
dwParam1
,
dwParam2
);
case
MIDM_GETNUMDEVS
:
return
1
;
case
MIDM_RESET
:
return
midReset
((
MIDIMAPDATA
*
)
dwUser
);
case
MIDM_START
:
return
midStart
((
MIDIMAPDATA
*
)
dwUser
);
case
MIDM_STOP
:
return
midStop
((
MIDIMAPDATA
*
)
dwUser
);
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 %
u
!
\n
"
,
wMsg
);
FIXME
(
"unknown message %
d
!
\n
"
,
wMsg
);
}
return
MMSYSERR_NOTSUPPORTED
;
}
...
...
@@ -274,18 +461,38 @@ DWORD WINAPI MIDIMAP_midMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
* Driver part *
*======================================================================*/
static
struct
WINE_MIDIMAP
*
oss
=
NULL
;
/**************************************************************************
* MIDIMAP_drvOpen [internal]
*/
static
DWORD
MIDIMAP_drvOpen
(
LPSTR
str
)
{
if
(
oss
)
MIDIOUTCAPSA
moc
;
unsigned
dev
,
i
;
if
(
midiOutPorts
)
return
0
;
/* I know, this is ugly, but who cares... */
oss
=
(
struct
WINE_MIDIMAP
*
)
1
;
numMidiOutPorts
=
midiOutGetNumDevs
();
midiOutPorts
=
HeapAlloc
(
GetProcessHeap
(),
0
,
numMidiOutPorts
*
sizeof
(
MIDIOUTPORT
));
for
(
dev
=
0
;
dev
<
numMidiOutPorts
;
dev
++
)
{
if
(
midiOutGetDevCapsA
((
HMIDIOUT
)
dev
,
&
moc
,
sizeof
(
moc
))
==
0L
)
{
strcpy
(
midiOutPorts
[
dev
].
name
,
moc
.
szPname
);
midiOutPorts
[
dev
].
loaded
=
0
;
midiOutPorts
[
dev
].
hMidi
=
0
;
midiOutPorts
[
dev
].
uDevID
=
0
;
midiOutPorts
[
dev
].
lpbPatch
=
NULL
;
for
(
i
=
0
;
i
<
16
;
i
++
)
midiOutPorts
[
dev
].
aChn
[
i
]
=
i
;
}
else
{
midiOutPorts
[
dev
].
loaded
=
-
1
;
}
}
return
1
;
}
...
...
@@ -294,8 +501,10 @@ static DWORD MIDIMAP_drvOpen(LPSTR str)
*/
static
DWORD
MIDIMAP_drvClose
(
DWORD
dwDevID
)
{
if
(
oss
)
{
oss
=
NULL
;
if
(
midiOutPorts
)
{
HeapFree
(
GetProcessHeap
(),
0
,
midiOutPorts
);
midiOutPorts
=
NULL
;
return
1
;
}
return
0
;
...
...
@@ -310,7 +519,8 @@ LONG CALLBACK MIDIMAP_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
/* EPP TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n", */
/* EPP dwDevID, hDriv, wMsg, dwParam1, dwParam2); */
switch
(
wMsg
)
{
switch
(
wMsg
)
{
case
DRV_LOAD
:
return
1
;
case
DRV_FREE
:
return
1
;
case
DRV_OPEN
:
return
MIDIMAP_drvOpen
((
LPSTR
)
dwParam1
);
...
...
dlls/winmm/midimap/midimap.drv.spec
View file @
beea6151
...
...
@@ -4,11 +4,11 @@ type win32
import winmm.dll
import user32.dll
import advapi32.dll
import kernel32.dll
import ntdll.dll
debug_channels (msacm)
@ stdcall DriverProc(long long long long long) MIDIMAP_DriverProc
@ stdcall midMessage(long long long long long) MIDIMAP_midMessage
@ stdcall modMessage(long long long long long) MIDIMAP_modMessage
winedefault.reg
View file @
beea6151
...
...
@@ -155,6 +155,16 @@
"ThreadingModel"="Both"
#
# Entries for Multimedia
#
# Midi Mapper
[HKEY_LOCAL_USER\Software\Microsoft\Windows\CurrentVersion\Multimedia\MIDIMap] 989041554
"AutoScheme"=dword:00000000
"CurrentInstrument"="#0"
"UseScheme"=dword:00000000
#
# Entries for IWebBrowser
# Used by Internet Explorer HTML-rendering control
#
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment