included DLL init sequence (from obsoleted init.c)
fixed builtin mmsystem.dll init sequence fixed PlaySound when used with an asynchronous audio driver fixed midiStream functions for Stop/Pause/Restart functions fixed error handling in waveOutOpen with QUERY_FORMAT flag
This commit is contained in:
parent
0eacb6f8c0
commit
06c7f93f68
|
@ -43,8 +43,77 @@ static UINT16 waveGetErrorText(UINT16 uError, LPSTR lpText, UINT16 uSize);
|
|||
LONG WINAPI DrvDefDriverProc(DWORD dwDevID, HDRVR16 hDrv, WORD wMsg,
|
||||
DWORD dwParam1, DWORD dwParam2);
|
||||
|
||||
static HINSTANCE WINMM_hInstance = 0;
|
||||
static HINSTANCE MMSYSTEM_hInstance = 0;
|
||||
|
||||
/**************************************************************************
|
||||
* MMSYSTEM_WEP [MMSYSTEM.1]
|
||||
* MULTIMEDIA_Init [internal]
|
||||
*/
|
||||
static BOOL MULTIMEDIA_Init()
|
||||
{
|
||||
static BOOL bInitDone = FALSE;
|
||||
|
||||
if (!bInitDone) {
|
||||
if (MULTIMEDIA_MidiInit() && MULTIMEDIA_MciInit() && MULTIMEDIA_MMTimeInit()) {
|
||||
bInitDone = TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* WINMM_LibMain [EntryPoint]
|
||||
*
|
||||
* WINMM DLL entry point
|
||||
*
|
||||
*/
|
||||
BOOL WINAPI WINMM_LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
||||
{
|
||||
TRACE("0x%x 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
|
||||
|
||||
switch (fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
if (!MULTIMEDIA_Init())
|
||||
return FALSE;
|
||||
WINMM_hInstance = hinstDLL;
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* MMSYSTEM_LibMain [EntryPoint]
|
||||
*
|
||||
* MMSYSTEM DLL entry point
|
||||
*
|
||||
*/
|
||||
BOOL WINAPI MMSYSTEM_LibMain(DWORD fdwReason, HINSTANCE hinstDLL, WORD ds,
|
||||
WORD wHeapSize, DWORD dwReserved1, WORD wReserved2)
|
||||
{
|
||||
TRACE("0x%x 0x%lx\n", hinstDLL, fdwReason);
|
||||
|
||||
switch (fdwReason) {
|
||||
case DLL_PROCESS_ATTACH:
|
||||
if (!MULTIMEDIA_Init())
|
||||
return FALSE;
|
||||
MMSYSTEM_hInstance = hinstDLL;
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* MMSYSTEM_WEP [MMSYSTEM.1]
|
||||
*/
|
||||
int WINAPI MMSYSTEM_WEP(HINSTANCE16 hInstance, WORD wDataSeg,
|
||||
WORD cbHeapSize, LPSTR lpCmdLine)
|
||||
|
@ -229,9 +298,12 @@ static BOOL16 WINAPI proc_PlaySound(LPCSTR lpszSoundName, UINT uFlags)
|
|||
/* waveHdr.dwBytesRecorded = count; */
|
||||
/* FIXME: doesn't expect async ops */
|
||||
wodMessage(0, WODM_WRITE, 0, (DWORD)&waveHdr, sizeof(WAVEHDR));
|
||||
while (!(waveHdr.dwFlags & WHDR_DONE))
|
||||
Sleep(10);
|
||||
}
|
||||
wodMessage(0, WODM_UNPREPARE, 0, (DWORD)&waveHdr, sizeof(WAVEHDR));
|
||||
wodMessage(0, WODM_CLOSE, 0, 0L, 0L);
|
||||
while (wodMessage(0, WODM_CLOSE, 0, 0L, 0L) == WAVERR_STILLPLAYING)
|
||||
Sleep(100);
|
||||
|
||||
bRet = TRUE;
|
||||
} else
|
||||
|
@ -1651,7 +1723,7 @@ UINT16 WINAPI mciLoadCommandResource16(HANDLE16 hinst, LPCSTR resname, UINT16 ty
|
|||
*/
|
||||
strcpy(buf,resname);
|
||||
strcat(buf, ".mci");
|
||||
if (OpenFile(buf, &ofs,OF_EXIST) != HFILE_ERROR) {
|
||||
if (OpenFile(buf, &ofs, OF_EXIST) != HFILE_ERROR) {
|
||||
xhinst = LoadLibrary16(buf);
|
||||
if (xhinst > 32)
|
||||
hinst = xhinst;
|
||||
|
@ -3076,9 +3148,13 @@ typedef struct WINE_MIDIStream{
|
|||
DWORD dwPulses;
|
||||
DWORD dwStartTicks;
|
||||
WORD wFlags;
|
||||
BOOL bFlag;
|
||||
HANDLE hEvent;
|
||||
LPMIDIHDR lpMidiHdr;
|
||||
} WINE_MIDIStream;
|
||||
|
||||
#define WINE_MSM_HEADER (WM_USER+0)
|
||||
#define WINE_MSM_STOP (WM_USER+1)
|
||||
|
||||
/**************************************************************************
|
||||
* MMSYSTEM_GetMidiStream [internal]
|
||||
*/
|
||||
|
@ -3099,9 +3175,9 @@ static BOOL MMSYSTEM_GetMidiStream(HMIDISTRM hMidiStrm, WINE_MIDIStream** lpMidi
|
|||
}
|
||||
|
||||
/**************************************************************************
|
||||
* MMSYSTEM_MidiStreamConvert [internal]
|
||||
* MMSYSTEM_MidiStream_Convert [internal]
|
||||
*/
|
||||
static DWORD MMSYSTEM_MidiStreamConvert(WINE_MIDIStream* lpMidiStrm, DWORD pulse)
|
||||
static DWORD MMSYSTEM_MidiStream_Convert(WINE_MIDIStream* lpMidiStrm, DWORD pulse)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
|
||||
|
@ -3120,15 +3196,135 @@ static DWORD MMSYSTEM_MidiStreamConvert(WINE_MIDIStream* lpMidiStrm, DWORD pulse
|
|||
}
|
||||
|
||||
/**************************************************************************
|
||||
* MMSYSTEM_MidiStreamPlayer [internal]
|
||||
* MMSYSTEM_MidiStream_MessageHandler [internal]
|
||||
*/
|
||||
static DWORD WINAPI MMSYSTEM_MidiStreamPlayer(LPVOID pmt)
|
||||
static BOOL MMSYSTEM_MidiStream_MessageHandler(WINE_MIDIStream* lpMidiStrm, LPMIDIOPENDESC lpDesc, LPMSG msg)
|
||||
{
|
||||
LPMIDIHDR lpMidiHdr;
|
||||
LPMIDIHDR* lpmh;
|
||||
LPBYTE lpData;
|
||||
|
||||
switch (msg->message) {
|
||||
case WM_QUIT:
|
||||
SetEvent(lpMidiStrm->hEvent);
|
||||
return FALSE;
|
||||
case WINE_MSM_STOP:
|
||||
TRACE("STOP\n");
|
||||
/* this is not quite what MS doc says... */
|
||||
midiOutReset(lpMidiStrm->hDevice);
|
||||
/* empty list of already submitted buffers */
|
||||
for (lpMidiHdr = lpMidiStrm->lpMidiHdr; lpMidiHdr; lpMidiHdr = (LPMIDIHDR)lpMidiHdr->lpNext) {
|
||||
lpMidiHdr->dwFlags |= MHDR_DONE;
|
||||
lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
|
||||
|
||||
DriverCallback16(lpDesc->dwCallback, lpMidiStrm->wFlags, lpMidiStrm->hDevice,
|
||||
MM_MOM_DONE, lpDesc->dwInstance, lpMidiHdr->reserved, 0L);
|
||||
}
|
||||
lpMidiStrm->lpMidiHdr = 0;
|
||||
SetEvent(lpMidiStrm->hEvent);
|
||||
break;
|
||||
case WINE_MSM_HEADER:
|
||||
/* sets initial tick count for first MIDIHDR */
|
||||
if (!lpMidiStrm->dwStartTicks)
|
||||
lpMidiStrm->dwStartTicks = GetTickCount();
|
||||
|
||||
/* FIXME(EPP): "I don't understand the content of the first MIDIHDR sent
|
||||
* by native mcimidi, it doesn't look like a correct one".
|
||||
* this trick allows to throw it away... but I don't like it.
|
||||
* It looks like part of the file I'm trying to play and definitively looks
|
||||
* like raw midi content
|
||||
* I'd really like to understand why native mcimidi sends it. Perhaps a bad
|
||||
* synchronization issue where native mcimidi is still processing raw MIDI
|
||||
* content before generating MIDIEVENTs ?
|
||||
*
|
||||
* 4c 04 89 3b 00 81 7c 99 3b 43 00 99 23 5e 04 89 L..;..|.;C..#^..
|
||||
* 3b 00 00 89 23 00 7c 99 3b 45 00 99 28 62 04 89 ;...#.|.;E..(b..
|
||||
* 3b 00 00 89 28 00 81 7c 99 3b 4e 00 99 23 5e 04 ;...(..|.;N..#^.
|
||||
* 89 3b 00 00 89 23 00 7c 99 3b 45 00 99 23 78 04 .;...#.|.;E..#x.
|
||||
* 89 3b 00 00 89 23 00 81 7c 99 3b 48 00 99 23 5e .;...#..|.;H..#^
|
||||
* 04 89 3b 00 00 89 23 00 7c 99 3b 4e 00 99 28 62 ..;...#.|.;N..(b
|
||||
* 04 89 3b 00 00 89 28 00 81 7c 99 39 4c 00 99 23 ..;...(..|.9L..#
|
||||
* 5e 04 89 39 00 00 89 23 00 82 7c 99 3b 4c 00 99 ^..9...#..|.;L..
|
||||
* 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 00 99 #^..;...#.|.;H..
|
||||
* 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b 3f 04 (b..;...(..|.;?.
|
||||
* 89 3b 00 1c 99 23 5e 04 89 23 00 5c 99 3b 45 00 .;...#^..#.\.;E.
|
||||
* 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 3b 46 .#x..;...#..|.;F
|
||||
* 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 ..#^..;...#.|.;H
|
||||
* 00 99 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b ..(b..;...(..|.;
|
||||
* 46 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b F..#^..;...#.|.;
|
||||
* 48 00 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 H..#x..;...#..|.
|
||||
* 3b 4c 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 ;L..#^..;...#.|.
|
||||
*/
|
||||
lpMidiHdr = (LPMIDIHDR)msg->lParam;
|
||||
lpData = ((DWORD)lpMidiHdr == lpMidiHdr->reserved) ?
|
||||
(LPBYTE)lpMidiHdr->lpData : (LPBYTE)PTR_SEG_TO_LIN(lpMidiHdr->lpData);
|
||||
TRACE("Adding %s lpMidiHdr=%p [lpData=0x%08lx dwBufferLength=%lu/%lu dwFlags=0x%08lx size=%u]\n",
|
||||
(lpMidiHdr->dwFlags & MHDR_ISSTRM) ? "stream" : "regular", lpMidiHdr,
|
||||
lpMidiHdr->reserved, lpMidiHdr->dwBufferLength, lpMidiHdr->dwBytesRecorded,
|
||||
lpMidiHdr->dwFlags, msg->wParam);
|
||||
#if 0
|
||||
/* dumps content of lpMidiHdr->lpData
|
||||
* FIXME: there should be a debug routine somewhere that already does this
|
||||
* I hate spreading this type of shit all around the code
|
||||
*/
|
||||
for (dwToGo = 0; dwToGo < lpMidiHdr->dwBufferLength; dwToGo += 16) {
|
||||
DWORD i;
|
||||
BYTE ch;
|
||||
|
||||
for (i = 0; i < MIN(16, lpMidiHdr->dwBufferLength - dwToGo); i++)
|
||||
printf("%02x ", lpData[dwToGo + i]);
|
||||
for (; i < 16; i++)
|
||||
printf(" ");
|
||||
for (i = 0; i < MIN(16, lpMidiHdr->dwBufferLength - dwToGo); i++) {
|
||||
ch = lpData[dwToGo + i];
|
||||
printf("%c", (ch >= 0x20 && ch <= 0x7F) ? ch : '.');
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
if (((LPMIDIEVENT)lpData)->dwStreamID != 0 &&
|
||||
((LPMIDIEVENT)lpData)->dwStreamID != 0xFFFFFFFF &&
|
||||
((LPMIDIEVENT)lpData)->dwStreamID != (DWORD)lpMidiStrm) {
|
||||
FIXME("Dropping bad %s lpMidiHdr (streamID=%08lx)\n",
|
||||
(lpMidiHdr->dwFlags & MHDR_ISSTRM) ? "stream" : "regular",
|
||||
((LPMIDIEVENT)lpData)->dwStreamID);
|
||||
lpMidiHdr->dwFlags |= MHDR_DONE;
|
||||
lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
|
||||
|
||||
DriverCallback16(lpDesc->dwCallback, lpMidiStrm->wFlags, lpMidiStrm->hDevice,
|
||||
MM_MOM_DONE, lpDesc->dwInstance, lpMidiHdr->reserved, 0L);
|
||||
break;
|
||||
}
|
||||
|
||||
for (lpmh = &lpMidiStrm->lpMidiHdr; *lpmh; lpmh = (LPMIDIHDR*)&((*lpmh)->lpNext));
|
||||
*lpmh = lpMidiHdr;
|
||||
lpMidiHdr = (LPMIDIHDR)msg->lParam;
|
||||
lpMidiHdr->lpNext = 0;
|
||||
lpMidiHdr->dwFlags |= MHDR_INQUEUE;
|
||||
lpMidiHdr->dwFlags &= MHDR_DONE;
|
||||
lpMidiHdr->dwOffset = 0;
|
||||
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown message %d\n", msg->message);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* MMSYSTEM_MidiStream_Player [internal]
|
||||
*/
|
||||
static DWORD CALLBACK MMSYSTEM_MidiStream_Player(LPVOID pmt)
|
||||
{
|
||||
WINE_MIDIStream* lpMidiStrm = pmt;
|
||||
MIDIOPENDESC* lpDesc = USER_HEAP_LIN_ADDR(lpMidiStrm->hDevice);
|
||||
MSG msg;
|
||||
DWORD dwToGo;
|
||||
DWORD dwCurrTC;
|
||||
LPMIDIHDR lpMidiHdr;
|
||||
LPMIDIEVENT me;
|
||||
LPBYTE lpData = 0;
|
||||
|
||||
TRACE("(%p)!\n", lpMidiStrm);
|
||||
|
||||
|
@ -3138,143 +3334,130 @@ static DWORD WINAPI MMSYSTEM_MidiStreamPlayer(LPVOID pmt)
|
|||
Callout.PeekMessageA(&msg, 0, 0, 0, 0);
|
||||
|
||||
/* FIXME: this next line must be called before midiStreamOut or midiStreamRestart are called */
|
||||
lpMidiStrm->bFlag = TRUE;
|
||||
SetEvent(lpMidiStrm->hEvent);
|
||||
TRACE("Ready to go 1\n");
|
||||
/* thread is started in paused mode */
|
||||
SuspendThread(lpMidiStrm->hThread);
|
||||
TRACE("Ready to go 2\n");
|
||||
|
||||
lpMidiStrm->dwStartTicks = 0;
|
||||
lpMidiStrm->dwPulses = 0;
|
||||
|
||||
while (Callout.GetMessageA(&msg, 0, 0, 0)) {
|
||||
LPMIDIHDR lpMidiHdr = (LPMIDIHDR)msg.lParam;
|
||||
LPMIDIEVENT me;
|
||||
LPBYTE lpData;
|
||||
lpMidiStrm->lpMidiHdr = 0;
|
||||
|
||||
switch (msg.message) {
|
||||
case WM_USER:
|
||||
TRACE("%s lpMidiHdr=%p [lpData=0x%08lx dwBufferLength=%lu/%lu dwFlags=0x%08lx]\n",
|
||||
(lpMidiHdr->dwFlags & MHDR_ISSTRM) ? "stream" : "regular", lpMidiHdr,
|
||||
lpMidiHdr->reserved, lpMidiHdr->dwBufferLength, lpMidiHdr->dwBytesRecorded, lpMidiHdr->dwFlags);
|
||||
for (;;) {
|
||||
lpMidiHdr = lpMidiStrm->lpMidiHdr;
|
||||
if (!lpMidiHdr) {
|
||||
/* for first message, block until one arrives, then process all that are available */
|
||||
Callout.GetMessageA(&msg, 0, 0, 0);
|
||||
do {
|
||||
if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm, lpDesc, &msg))
|
||||
goto the_end;
|
||||
} while (Callout.PeekMessageA(&msg, 0, 0, 0, PM_REMOVE));
|
||||
lpData = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* <HACK>
|
||||
* midiOutPrepareHeader(), in Wine, sets the 'reserved' field of MIDIHDR to the
|
||||
* 16 or 32 bit address of lpMidiHdr (depending if called from 16 to 32 bit code)
|
||||
*/
|
||||
/* <HACK>
|
||||
* midiOutPrepareHeader(), in Wine, sets the 'reserved' field of MIDIHDR to the
|
||||
* 16 or 32 bit address of lpMidiHdr (depending if called from 16 to 32 bit code)
|
||||
*/
|
||||
if (!lpData)
|
||||
lpData = ((DWORD)lpMidiHdr == lpMidiHdr->reserved) ?
|
||||
(LPBYTE)lpMidiHdr->lpData : (LPBYTE)PTR_SEG_TO_LIN(lpMidiHdr->lpData);
|
||||
|
||||
me = (LPMIDIEVENT)(lpData + lpMidiHdr->dwOffset);
|
||||
|
||||
/* do we have to wait ? */
|
||||
if (me->dwDeltaTime) {
|
||||
lpMidiStrm->dwPositionMS += MMSYSTEM_MidiStream_Convert(lpMidiStrm, me->dwDeltaTime);
|
||||
lpMidiStrm->dwPulses += me->dwDeltaTime;
|
||||
|
||||
#if 0
|
||||
/* dumps content of lpMidiHdr->lpData
|
||||
* FIXME: there should be a debug routine somewhere that already does this
|
||||
* I hate spreading this type of shit all around the code
|
||||
*/
|
||||
for (dwToGo = 0; dwToGo < lpMidiHdr->dwBufferLength; dwToGo += 16) {
|
||||
DWORD i;
|
||||
BYTE ch;
|
||||
|
||||
for (i = 0; i < MIN(16, lpMidiHdr->dwBufferLength - dwToGo); i++)
|
||||
printf("%02x ", lpData[dwToGo + i]);
|
||||
for (; i < 16; i++)
|
||||
printf(" ");
|
||||
for (i = 0; i < MIN(16, lpMidiHdr->dwBufferLength - dwToGo); i++) {
|
||||
ch = lpData[dwToGo + i];
|
||||
printf("%c", (ch >= 0x20 && ch <= 0x7F) ? ch : '.');
|
||||
dwToGo = lpMidiStrm->dwStartTicks + lpMidiStrm->dwPositionMS;
|
||||
|
||||
TRACE("%ld/%ld/%ld\n", dwToGo, GetTickCount(), me->dwDeltaTime);
|
||||
while ((dwCurrTC = GetTickCount()) < dwToGo) {
|
||||
if (MsgWaitForMultipleObjects(0, NULL, FALSE, dwToGo - dwCurrTC, QS_ALLINPUT) == WAIT_OBJECT_0) {
|
||||
/* got a message, handle it */
|
||||
while (Callout.PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
|
||||
if (!MMSYSTEM_MidiStream_MessageHandler(lpMidiStrm, lpDesc, &msg))
|
||||
goto the_end;
|
||||
}
|
||||
lpData = 0;
|
||||
} else {
|
||||
/* timeout, so me->dwDeltaTime is elapsed, can break the while loop */
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
/* FIXME: EPP says "I don't understand the content of the first MIDIHDR sent
|
||||
* by native mcimidi, it doesn't look like a correct one".
|
||||
* this trick allows to throw it away... but I don't like it.
|
||||
* It looks like part of the file I'm trying to play and definitively looks
|
||||
* like raw midi content
|
||||
* I'd really like to understand why native mcimidi sends it. Perhaps a bad
|
||||
* synchronization issue where native mcimidi is still processing raw MIDI
|
||||
* content before generating MIDIEVENTs ?
|
||||
*
|
||||
* 4c 04 89 3b 00 81 7c 99 3b 43 00 99 23 5e 04 89 L..;..|.;C..#^..
|
||||
* 3b 00 00 89 23 00 7c 99 3b 45 00 99 28 62 04 89 ;...#.|.;E..(b..
|
||||
* 3b 00 00 89 28 00 81 7c 99 3b 4e 00 99 23 5e 04 ;...(..|.;N..#^.
|
||||
* 89 3b 00 00 89 23 00 7c 99 3b 45 00 99 23 78 04 .;...#.|.;E..#x.
|
||||
* 89 3b 00 00 89 23 00 81 7c 99 3b 48 00 99 23 5e .;...#..|.;H..#^
|
||||
* 04 89 3b 00 00 89 23 00 7c 99 3b 4e 00 99 28 62 ..;...#.|.;N..(b
|
||||
* 04 89 3b 00 00 89 28 00 81 7c 99 39 4c 00 99 23 ..;...(..|.9L..#
|
||||
* 5e 04 89 39 00 00 89 23 00 82 7c 99 3b 4c 00 99 ^..9...#..|.;L..
|
||||
* 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 00 99 #^..;...#.|.;H..
|
||||
* 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b 3f 04 (b..;...(..|.;?.
|
||||
* 89 3b 00 1c 99 23 5e 04 89 23 00 5c 99 3b 45 00 .;...#^..#.\.;E.
|
||||
* 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 3b 46 .#x..;...#..|.;F
|
||||
* 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b 48 ..#^..;...#.|.;H
|
||||
* 00 99 28 62 04 89 3b 00 00 89 28 00 81 7c 99 3b ..(b..;...(..|.;
|
||||
* 46 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 3b F..#^..;...#.|.;
|
||||
* 48 00 99 23 78 04 89 3b 00 00 89 23 00 81 7c 99 H..#x..;...#..|.
|
||||
* 3b 4c 00 99 23 5e 04 89 3b 00 00 89 23 00 7c 99 ;L..#^..;...#.|.
|
||||
*/
|
||||
if (((LPMIDIEVENT)lpData)->dwStreamID != 0 &&
|
||||
((LPMIDIEVENT)lpData)->dwStreamID != 0xFFFFFFFF &&
|
||||
((LPMIDIEVENT)lpData)->dwStreamID != (DWORD)lpMidiStrm) {
|
||||
FIXME("Dropping bad lpMidiHdr (streamID=%08lx)\n", ((LPMIDIEVENT)lpData)->dwStreamID);
|
||||
} else {
|
||||
/* sets initial tick count for first MIDIHDR */
|
||||
if (!lpMidiStrm->dwStartTicks)
|
||||
lpMidiStrm->dwStartTicks = GetTickCount();
|
||||
|
||||
for (lpMidiHdr->dwOffset = 0; lpMidiHdr->dwOffset < lpMidiHdr->dwBufferLength; ) {
|
||||
me = (LPMIDIEVENT)(lpData + lpMidiHdr->dwOffset);
|
||||
|
||||
if (me->dwDeltaTime) {
|
||||
lpMidiStrm->dwPositionMS += MMSYSTEM_MidiStreamConvert(lpMidiStrm, me->dwDeltaTime);
|
||||
dwToGo = lpMidiStrm->dwStartTicks + lpMidiStrm->dwPositionMS;
|
||||
dwCurrTC = GetTickCount();
|
||||
|
||||
lpMidiStrm->dwPulses += me->dwDeltaTime;
|
||||
|
||||
TRACE("%ld/%ld/%ld\n", dwToGo, dwCurrTC, me->dwDeltaTime);
|
||||
if (dwCurrTC < dwToGo)
|
||||
Sleep(dwToGo - dwCurrTC);
|
||||
}
|
||||
switch (MEVT_EVENTTYPE(me->dwEvent & ~MEVT_F_CALLBACK)) {
|
||||
case MEVT_COMMENT:
|
||||
FIXME("NIY: MEVT_COMMENT\n");
|
||||
/* do nothing, skip bytes */
|
||||
break;
|
||||
case MEVT_LONGMSG:
|
||||
FIXME("NIY: MEVT_LONGMSG, aka sending Sysex event\n");
|
||||
break;
|
||||
case MEVT_NOP:
|
||||
break;
|
||||
case MEVT_SHORTMSG:
|
||||
midiOutShortMsg(lpMidiStrm->hDevice, MEVT_EVENTPARM(me->dwEvent));
|
||||
break;
|
||||
case MEVT_TEMPO:
|
||||
lpMidiStrm->dwTempo = MEVT_EVENTPARM(me->dwEvent);
|
||||
break;
|
||||
case MEVT_VERSION:
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown MEVT (0x%02x)\n", MEVT_EVENTTYPE(me->dwEvent & ~MEVT_F_CALLBACK));
|
||||
break;
|
||||
}
|
||||
lpMidiHdr->dwOffset += sizeof(MIDIEVENT) + ((me->dwEvent & MEVT_F_LONG) ? ((MEVT_EVENTPARM(me->dwEvent) + 3) & ~3): 0);
|
||||
if (me->dwEvent & MEVT_F_CALLBACK) {
|
||||
DriverCallback16(lpDesc->dwCallback, lpMidiStrm->wFlags, lpMidiStrm->hDevice,
|
||||
MM_MOM_POSITIONCB, lpDesc->dwInstance, (LPARAM)lpMidiHdr, 0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (MEVT_EVENTTYPE(me->dwEvent & ~MEVT_F_CALLBACK)) {
|
||||
case MEVT_COMMENT:
|
||||
FIXME("NIY: MEVT_COMMENT\n");
|
||||
/* do nothing, skip bytes */
|
||||
break;
|
||||
case MEVT_LONGMSG:
|
||||
FIXME("NIY: MEVT_LONGMSG, aka sending Sysex event\n");
|
||||
break;
|
||||
case MEVT_NOP:
|
||||
break;
|
||||
case MEVT_SHORTMSG:
|
||||
midiOutShortMsg(lpMidiStrm->hDevice, MEVT_EVENTPARM(me->dwEvent));
|
||||
break;
|
||||
case MEVT_TEMPO:
|
||||
lpMidiStrm->dwTempo = MEVT_EVENTPARM(me->dwEvent);
|
||||
break;
|
||||
case MEVT_VERSION:
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown MEVT (0x%02x)\n", MEVT_EVENTTYPE(me->dwEvent & ~MEVT_F_CALLBACK));
|
||||
break;
|
||||
}
|
||||
if (me->dwEvent & MEVT_F_CALLBACK) {
|
||||
DriverCallback16(lpDesc->dwCallback, lpMidiStrm->wFlags, lpMidiStrm->hDevice,
|
||||
MM_MOM_POSITIONCB, lpDesc->dwInstance, (LPARAM)lpMidiHdr, 0L);
|
||||
}
|
||||
lpMidiHdr->dwOffset += sizeof(MIDIEVENT);
|
||||
if (me->dwEvent & MEVT_F_LONG)
|
||||
lpMidiHdr->dwOffset += (MEVT_EVENTPARM(me->dwEvent) + 3) & ~3;
|
||||
if (lpMidiHdr->dwOffset >= lpMidiHdr->dwBufferLength) {
|
||||
/* done with this header */
|
||||
lpMidiHdr->dwFlags |= MHDR_DONE;
|
||||
lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
|
||||
|
||||
lpMidiStrm->lpMidiHdr = (LPMIDIHDR)lpMidiHdr->lpNext;
|
||||
DriverCallback16(lpDesc->dwCallback, lpMidiStrm->wFlags, lpMidiStrm->hDevice,
|
||||
MM_MOM_DONE, lpDesc->dwInstance, lpMidiHdr->reserved, 0L);
|
||||
break;
|
||||
default:
|
||||
WARN("Unknown message %d\n", msg.message);
|
||||
break;
|
||||
lpData = 0;
|
||||
}
|
||||
}
|
||||
return msg.wParam;
|
||||
the_end:
|
||||
TRACE("End of thread\n");
|
||||
ExitThread(0);
|
||||
return 0; /* for removing the warning, never executed */
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* MMSYSTEM_MidiStream_PostMessage [internal]
|
||||
*/
|
||||
static BOOL MMSYSTEM_MidiStream_PostMessage(WINE_MIDIStream* lpMidiStrm, WORD msg, DWORD pmt1, DWORD pmt2)
|
||||
{
|
||||
if (Callout.PostThreadMessageA(lpMidiStrm->dwThreadID, msg, pmt1, pmt2)) {
|
||||
DWORD count;
|
||||
BOOL bHasWin16Lock;
|
||||
|
||||
/* FIXME: should use the new syslevel APIs */
|
||||
if ((bHasWin16Lock = _ConfirmWin16Lock()) != 0) {
|
||||
ReleaseThunkLock(&count);
|
||||
}
|
||||
WaitForSingleObject(lpMidiStrm->hEvent, INFINITE);
|
||||
if (bHasWin16Lock) {
|
||||
RestoreThunkLock(count);
|
||||
}
|
||||
} else {
|
||||
WARN("bad PostThreadMessageA\n");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -3290,18 +3473,19 @@ MMRESULT WINAPI midiStreamClose(HMIDISTRM hMidiStrm)
|
|||
return MMSYSERR_INVALHANDLE;
|
||||
|
||||
midiStreamStop(hMidiStrm);
|
||||
|
||||
USER_HEAP_FREE(hMidiStrm);
|
||||
MMSYSTEM_MidiStream_PostMessage(lpMidiStrm, WM_QUIT, 0, 0);
|
||||
HeapFree(GetProcessHeap(), 0, lpMidiStrm);
|
||||
CloseHandle(lpMidiStrm->hEvent);
|
||||
|
||||
return midiOutClose(hMidiStrm);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* MMSYSTEM_MidiStreamOpen [WINMM.91]
|
||||
* MMSYSTEM_MidiStream_Open [internal]
|
||||
*/
|
||||
static MMRESULT WINAPI MMSYSTEM_MidiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID,
|
||||
DWORD cMidi, DWORD dwCallback,
|
||||
DWORD dwInstance, DWORD fdwOpen)
|
||||
static MMRESULT WINAPI MMSYSTEM_MidiStream_Open(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID,
|
||||
DWORD cMidi, DWORD dwCallback,
|
||||
DWORD dwInstance, DWORD fdwOpen)
|
||||
{
|
||||
WINE_MIDIStream* lpMidiStrm;
|
||||
MMRESULT ret;
|
||||
|
@ -3321,6 +3505,9 @@ static MMRESULT WINAPI MMSYSTEM_MidiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lp
|
|||
}
|
||||
|
||||
lpMidiStrm = HeapAlloc(GetProcessHeap(), 0, sizeof(WINE_MIDIStream));
|
||||
if (!lpMidiStrm)
|
||||
return MMSYSERR_NOMEM;
|
||||
|
||||
lpMidiStrm->dwTempo = 500000;
|
||||
lpMidiStrm->dwTimeDiv = 480; /* 480 is 120 quater notes per minute *//* FIXME ??*/
|
||||
lpMidiStrm->dwPositionMS = 0;
|
||||
|
@ -3336,10 +3523,10 @@ static MMRESULT WINAPI MMSYSTEM_MidiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lp
|
|||
lpDesc->wDevID = *lpuDeviceID;
|
||||
ret = modMessage(lpDesc->wDevID, MODM_OPEN,
|
||||
lpDesc->dwInstance, (DWORD)lpDesc, fdwOpen);
|
||||
lpMidiStrm->bFlag = FALSE;
|
||||
lpMidiStrm->hEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
lpMidiStrm->wFlags = HIWORD(fdwOpen);
|
||||
|
||||
lpMidiStrm->hThread = CreateThread(NULL, 0, MMSYSTEM_MidiStreamPlayer,
|
||||
lpMidiStrm->hThread = CreateThread(NULL, 0, MMSYSTEM_MidiStream_Player,
|
||||
lpMidiStrm, 0, &(lpMidiStrm->dwThreadID));
|
||||
|
||||
if (!lpMidiStrm->hThread) {
|
||||
|
@ -3348,16 +3535,21 @@ static MMRESULT WINAPI MMSYSTEM_MidiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lp
|
|||
}
|
||||
|
||||
/* wait for thread to have started, and for it's queue to be created */
|
||||
while (!((volatile WINE_MIDIStream*)lpMidiStrm)->bFlag) {
|
||||
{
|
||||
DWORD count;
|
||||
|
||||
BOOL bHasWin16Lock;
|
||||
|
||||
/* (Release|Restore)ThunkLock() is needed when this method is called from 16 bit code,
|
||||
* (meaning the Win16Lock is set), so that it's released and the 32 bit thread running
|
||||
* MMSYSTEM_MidiStreamPlayer can acquire Win16Lock to create its queue.
|
||||
*/
|
||||
ReleaseThunkLock(&count);
|
||||
Sleep(1);
|
||||
RestoreThunkLock(count);
|
||||
if ((bHasWin16Lock = _ConfirmWin16Lock()) != 0) {
|
||||
ReleaseThunkLock(&count);
|
||||
}
|
||||
WaitForSingleObject(lpMidiStrm->hEvent, INFINITE);
|
||||
if (bHasWin16Lock) {
|
||||
RestoreThunkLock(count);
|
||||
}
|
||||
}
|
||||
|
||||
TRACE("=> (%u/%d) hMidi=0x%04x ret=%d lpMidiStrm=%p\n", *lpuDeviceID, lpDesc->wDevID, *lphMidiStrm, ret, lpMidiStrm);
|
||||
|
@ -3371,7 +3563,7 @@ MMRESULT WINAPI midiStreamOpen(HMIDISTRM* lphMidiStrm, LPUINT lpuDeviceID,
|
|||
DWORD cMidi, DWORD dwCallback,
|
||||
DWORD dwInstance, DWORD fdwOpen)
|
||||
{
|
||||
return MMSYSTEM_MidiStreamOpen(lphMidiStrm, lpuDeviceID, cMidi, dwCallback, dwInstance, CALLBACK32CONV(fdwOpen));
|
||||
return MMSYSTEM_MidiStream_Open(lphMidiStrm, lpuDeviceID, cMidi, dwCallback, dwInstance, CALLBACK32CONV(fdwOpen));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -3387,8 +3579,9 @@ MMRESULT WINAPI midiStreamOut(HMIDISTRM hMidiStrm, LPMIDIHDR lpMidiHdr, UINT cbM
|
|||
if (!MMSYSTEM_GetMidiStream(hMidiStrm, &lpMidiStrm, NULL)) {
|
||||
ret = MMSYSERR_INVALHANDLE;
|
||||
} else {
|
||||
if (!Callout.PostThreadMessageA(lpMidiStrm->dwThreadID, WM_USER, 0, (DWORD)lpMidiHdr)) {
|
||||
if (!Callout.PostThreadMessageA(lpMidiStrm->dwThreadID, WINE_MSM_HEADER, cbMidiHdr, (DWORD)lpMidiHdr)) {
|
||||
WARN("bad PostThreadMessageA\n");
|
||||
ret = MMSYSERR_ERROR;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -3409,7 +3602,8 @@ MMRESULT WINAPI midiStreamPause(HMIDISTRM hMidiStrm)
|
|||
} else {
|
||||
if (SuspendThread(lpMidiStrm->hThread) == 0xFFFFFFFF) {
|
||||
WARN("bad Suspend (%ld)\n", GetLastError());
|
||||
}
|
||||
ret = MMSYSERR_ERROR;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -3508,7 +3702,10 @@ MMRESULT WINAPI midiStreamRestart(HMIDISTRM hMidiStrm)
|
|||
} else {
|
||||
if (ResumeThread(lpMidiStrm->hThread) == 0xFFFFFFFF) {
|
||||
WARN("bad Resume (%ld)\n", GetLastError());
|
||||
}
|
||||
ret = MMSYSERR_ERROR;
|
||||
} else {
|
||||
lpMidiStrm->dwStartTicks = GetTickCount() - lpMidiStrm->dwPositionMS;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -3521,14 +3718,14 @@ MMRESULT WINAPI midiStreamStop(HMIDISTRM hMidiStrm)
|
|||
WINE_MIDIStream* lpMidiStrm;
|
||||
MMRESULT ret = MMSYSERR_NOERROR;
|
||||
|
||||
FIXME("(%08x) stub!\n", hMidiStrm);
|
||||
TRACE("(%08x)!\n", hMidiStrm);
|
||||
|
||||
if (!MMSYSTEM_GetMidiStream(hMidiStrm, &lpMidiStrm, NULL)) {
|
||||
ret = MMSYSERR_INVALHANDLE;
|
||||
} else {
|
||||
/* FIXME: should turn off all notes, and return all buffers to
|
||||
* calling application
|
||||
*/
|
||||
/* in case stream has been paused... FIXME is the current state correct ? */
|
||||
midiStreamRestart(hMidiStrm);
|
||||
MMSYSTEM_MidiStream_PostMessage(lpMidiStrm, WINE_MSM_STOP, 0, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -3555,7 +3752,7 @@ MMRESULT16 WINAPI midiStreamOpen16(HMIDISTRM16* phMidiStrm, LPUINT16 devid,
|
|||
if (!phMidiStrm || !devid)
|
||||
return MMSYSERR_INVALPARAM;
|
||||
devid32 = *devid;
|
||||
ret = MMSYSTEM_MidiStreamOpen(&hMidiStrm32, &devid32, cMidi, dwCallback, dwInstance, fdwOpen);
|
||||
ret = MMSYSTEM_MidiStream_Open(&hMidiStrm32, &devid32, cMidi, dwCallback, dwInstance, fdwOpen);
|
||||
*phMidiStrm = hMidiStrm32;
|
||||
*devid = devid32;
|
||||
return ret;
|
||||
|
@ -3808,9 +4005,9 @@ UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
|
|||
const LPWAVEFORMATEX lpFormat, DWORD dwCallback,
|
||||
DWORD dwInstance, DWORD dwFlags)
|
||||
{
|
||||
HWAVEOUT16 hWaveOut;
|
||||
HWAVEOUT16 hWaveOut;
|
||||
LPWAVEOPENDESC lpDesc;
|
||||
DWORD dwRet = 0;
|
||||
DWORD dwRet = MMSYSERR_NOERROR;
|
||||
BOOL bMapperFlg = FALSE;
|
||||
|
||||
TRACE("(%p, %d, %p, %08lX, %08lX, %08lX);\n",
|
||||
|
@ -3825,7 +4022,7 @@ UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
|
|||
if (lpFormat == NULL) return WAVERR_BADFORMAT;
|
||||
|
||||
hWaveOut = USER_HEAP_ALLOC(sizeof(WAVEOPENDESC));
|
||||
if (lphWaveOut != NULL) *lphWaveOut = hWaveOut;
|
||||
if (hWaveOut == 0) return MMSYSERR_NOMEM;
|
||||
lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut);
|
||||
if (lpDesc == NULL) return MMSYSERR_NOMEM;
|
||||
lpDesc->hWave = hWaveOut;
|
||||
|
@ -3845,14 +4042,16 @@ UINT16 WINAPI waveOutOpen16(HWAVEOUT16* lphWaveOut, UINT16 uDeviceID,
|
|||
lpDesc->uDeviceID = uDeviceID; /* save physical Device ID */
|
||||
if (dwFlags & WAVE_FORMAT_QUERY) {
|
||||
TRACE("End of WAVE_FORMAT_QUERY !\n");
|
||||
dwRet = waveOutClose(hWaveOut);
|
||||
if (lphWaveOut) *lphWaveOut = 0;
|
||||
USER_HEAP_FREE(hWaveOut);
|
||||
hWaveOut = 0;
|
||||
}
|
||||
else if (dwRet != MMSYSERR_NOERROR)
|
||||
{
|
||||
USER_HEAP_FREE(hWaveOut);
|
||||
if (lphWaveOut) *lphWaveOut = 0;
|
||||
hWaveOut = 0;
|
||||
}
|
||||
if (lphWaveOut != NULL) *lphWaveOut = hWaveOut;
|
||||
TRACE("=> %ld\n", dwRet);
|
||||
return dwRet;
|
||||
}
|
||||
|
||||
|
@ -4094,16 +4293,16 @@ UINT16 WINAPI waveOutGetPosition16(HWAVEOUT16 hWaveOut, LPMMTIME16 lpTime,
|
|||
UINT16 WINAPI waveOut##xx##16(HWAVEOUT16 hWaveOut, atype x) \
|
||||
{ \
|
||||
LPWAVEOPENDESC lpDesc; \
|
||||
TRACE("(%04X, %08lx);\n", hWaveOut, (DWORD)x); \
|
||||
TRACE("(%04X, %08lx);\n", hWaveOut, (DWORD)x); \
|
||||
lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveOut); \
|
||||
if (lpDesc == NULL) return MMSYSERR_INVALHANDLE; \
|
||||
return wodMessage(lpDesc->uDeviceID, WODM_##XX, \
|
||||
lpDesc->dwInstance, (DWORD)x, 0L); \
|
||||
}
|
||||
|
||||
WAVEOUT_SHORTCUT_1(GetPitch, GETPITCH, DWORD*)
|
||||
WAVEOUT_SHORTCUT_1(GetPitch, GETPITCH, LPDWORD)
|
||||
WAVEOUT_SHORTCUT_1(SetPitch, SETPITCH, DWORD)
|
||||
WAVEOUT_SHORTCUT_1(GetPlaybackRate, GETPLAYBACKRATE, DWORD*)
|
||||
WAVEOUT_SHORTCUT_1(GetPlaybackRate, GETPLAYBACKRATE, LPDWORD)
|
||||
WAVEOUT_SHORTCUT_1(SetPlaybackRate, SETPLAYBACKRATE, DWORD)
|
||||
|
||||
#define WAVEOUT_SHORTCUT_2(xx, XX, atype) \
|
||||
|
@ -4113,11 +4312,11 @@ WAVEOUT_SHORTCUT_1(SetPlaybackRate, SETPLAYBACKRATE, DWORD)
|
|||
} \
|
||||
UINT16 WINAPI waveOut##xx##16(UINT16 devid, atype x) \
|
||||
{ \
|
||||
TRACE("(%04X, %08lx);\n", devid, (DWORD)x); \
|
||||
return wodMessage(devid, WODM_##XX, 0L, (DWORD)x, 0L); \
|
||||
TRACE("(%04X, %08lx);\n", devid, (DWORD)x); \
|
||||
return wodMessage(devid, WODM_##XX, 0, (DWORD)x, 0L); \
|
||||
}
|
||||
|
||||
WAVEOUT_SHORTCUT_2(GetVolume, GETVOLUME, DWORD*)
|
||||
WAVEOUT_SHORTCUT_2(GetVolume, GETVOLUME, LPDWORD)
|
||||
WAVEOUT_SHORTCUT_2(SetVolume, SETVOLUME, DWORD)
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -4133,7 +4332,7 @@ UINT WINAPI waveOutBreakLoop(HWAVEOUT hWaveOut)
|
|||
*/
|
||||
UINT16 WINAPI waveOutBreakLoop16(HWAVEOUT16 hWaveOut)
|
||||
{
|
||||
TRACE("(%04X)\n", hWaveOut);
|
||||
FIXME("(%04X)\n", hWaveOut);
|
||||
return MMSYSERR_INVALHANDLE;
|
||||
}
|
||||
|
||||
|
@ -4916,7 +5115,7 @@ void mmTaskEntryPoint16(LPSTR cmdLine, WORD di, WORD si)
|
|||
{
|
||||
int len = cmdLine[0x80];
|
||||
|
||||
if (len/2 == 6) {
|
||||
if (len / 2 == 6) {
|
||||
void (*fpProc)(DWORD) = (void (*)(DWORD))PTR_SEG_TO_LIN(*((DWORD*)(cmdLine + 1)));
|
||||
DWORD dwPmt = *((DWORD*)(cmdLine + 5));
|
||||
|
||||
|
@ -5233,18 +5432,13 @@ HANDLE16 WINAPI mmThreadGetTask16(HANDLE16 hndl)
|
|||
/**************************************************************************
|
||||
* mmThreadGetTask [internal]
|
||||
*/
|
||||
void WINAPI WINE_mmThreadEntryPoint(DWORD _pmt)
|
||||
void CALLBACK WINE_mmThreadEntryPoint(DWORD _pmt)
|
||||
{
|
||||
HANDLE16 hndl = (HANDLE16)_pmt;
|
||||
WINE_MMTHREAD* lpMMThd = (WINE_MMTHREAD*)PTR_SEG_OFF_TO_LIN(hndl, 0);
|
||||
CRITICAL_SECTION* cs;
|
||||
|
||||
TRACE("(%04x %p)\n", hndl, lpMMThd);
|
||||
|
||||
GetpWin16Lock(&cs);
|
||||
|
||||
TRACE("lc=%ld rc=%ld ot=%08lx\n", cs->LockCount, cs->RecursionCount, (DWORD)cs->OwningThread);
|
||||
|
||||
lpMMThd->hTask = LOWORD(GetCurrentTask());
|
||||
TRACE("[10-%08x] setting hTask to 0x%08x\n", lpMMThd->hThread, lpMMThd->hTask);
|
||||
lpMMThd->dwStatus = 0x10;
|
||||
|
@ -5252,13 +5446,7 @@ void WINAPI WINE_mmThreadEntryPoint(DWORD _pmt)
|
|||
TRACE("[20-%08x]\n", lpMMThd->hThread);
|
||||
lpMMThd->dwStatus = 0x20;
|
||||
if (lpMMThd->fpThread) {
|
||||
#if 0
|
||||
extern DWORD CALLBACK CallTo16_long_l_x(FARPROC16, DWORD);
|
||||
TRACE("Calling %08lx(%08lx)\n", (DWORD)lpMMThd->fpThread, lpMMThd->dwThreadPmt);$
|
||||
CallTo16_long_l_x(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
|
||||
#else
|
||||
Callbacks->CallWOWCallbackProc(lpMMThd->fpThread, lpMMThd->dwThreadPmt);
|
||||
#endif
|
||||
}
|
||||
lpMMThd->dwStatus = 0x30;
|
||||
TRACE("[30-%08x]\n", lpMMThd->hThread);
|
||||
|
@ -5273,18 +5461,16 @@ void WINAPI WINE_mmThreadEntryPoint(DWORD _pmt)
|
|||
if (lpMMThd->hEvent)
|
||||
CloseHandle(lpMMThd->hEvent);
|
||||
GlobalFree16(hndl);
|
||||
TRACE("lc=%ld rc=%ld ot=%08lx\n", cs->LockCount, cs->RecursionCount, (DWORD)cs->OwningThread);
|
||||
TRACE("done\n");
|
||||
}
|
||||
|
||||
|
||||
typedef BOOL16 (WINAPI *MMCPLCALLBACK)(HWND, LPSTR, LPSTR, LPSTR);
|
||||
typedef BOOL16 (WINAPI *MMCPLCALLBACK)(HWND, LPCSTR, LPCSTR, LPCSTR);
|
||||
|
||||
/**************************************************************************
|
||||
* mmShowMMCPLPropertySheet [MMSYSTEM.1150]
|
||||
*/
|
||||
BOOL16 WINAPI mmShowMMCPLPropertySheet16(HWND hWnd, char* lpStrDevice,
|
||||
char* lpStrTab, char* lpStrTitle)
|
||||
BOOL16 WINAPI mmShowMMCPLPropertySheet16(HWND hWnd, LPCSTR lpStrDevice,
|
||||
LPCSTR lpStrTab, LPCSTR lpStrTitle)
|
||||
{
|
||||
HANDLE hndl;
|
||||
BOOL16 ret = FALSE;
|
||||
|
@ -5294,11 +5480,7 @@ BOOL16 WINAPI mmShowMMCPLPropertySheet16(HWND hWnd, char* lpStrDevice,
|
|||
hndl = LoadLibraryA("MMSYS.CPL");
|
||||
if (hndl != 0) {
|
||||
MMCPLCALLBACK fp = (MMCPLCALLBACK)GetProcAddress(hndl, "ShowMMCPLPropertySheet");
|
||||
if (fp != NULL) {
|
||||
/* FIXME: wine hangs and/or seg faults in this call,
|
||||
* after the window is correctly displayed
|
||||
*/
|
||||
TRACE("Ready to go ThreadID=%08lx\n", GetCurrentThreadId());
|
||||
if (fp != NULL) {
|
||||
SYSLEVEL_ReleaseWin16Lock();
|
||||
ret = (fp)(hWnd, lpStrDevice, lpStrTab, lpStrTitle);
|
||||
SYSLEVEL_RestoreWin16Lock();
|
||||
|
|
Loading…
Reference in New Issue