mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-29 04:13:32 +00:00
[MCISEQ]
* Sync with Wine 1.7.1. CORE-7469 svn path=/trunk/; revision=60273
This commit is contained in:
@@ -9,12 +9,9 @@ list(APPEND SOURCE
|
||||
${CMAKE_CURRENT_BINARY_DIR}/mciseq.def)
|
||||
|
||||
add_library(mciseq SHARED ${SOURCE})
|
||||
|
||||
set_module_type(mciseq win32dll)
|
||||
|
||||
target_link_libraries(mciseq wine)
|
||||
add_importlibs(mciseq msvcrt winmm user32 kernel32 ntdll)
|
||||
add_dependencies(mciseq psdk)
|
||||
add_importlibs(mciseq winmm user32 msvcrt kernel32 ntdll)
|
||||
add_cd_file(TARGET mciseq DESTINATION reactos/system32 FOR all)
|
||||
|
||||
if(NOT MSVC)
|
||||
|
||||
+191
-189
@@ -64,6 +64,7 @@ typedef struct tagWINE_MCIMIDI {
|
||||
HMIDI hMidi;
|
||||
int nUseCount; /* Incremented for each shared open */
|
||||
HANDLE hCallback; /* Callback handle for pending notification */
|
||||
HANDLE hThread; /* Player thread */
|
||||
HMMIO hFile; /* mmio file handle open as Element */
|
||||
LPWSTR lpstrElementName; /* Name of file (if any) */
|
||||
LPWSTR lpstrCopyright;
|
||||
@@ -79,83 +80,30 @@ typedef struct tagWINE_MCIMIDI {
|
||||
MCI_MIDITRACK* tracks; /* Content of each track */
|
||||
DWORD dwPulse;
|
||||
DWORD dwPositionMS;
|
||||
DWORD dwEndMS;
|
||||
DWORD dwStartTicks;
|
||||
} WINE_MCIMIDI;
|
||||
|
||||
/* ===================================================================
|
||||
* ===================================================================
|
||||
* FIXME: should be using the new mmThreadXXXX functions from WINMM
|
||||
* instead of those
|
||||
* it would require to add a wine internal flag to mmThreadCreate
|
||||
* in order to pass a 32 bit function instead of a 16 bit
|
||||
* ===================================================================
|
||||
* =================================================================== */
|
||||
|
||||
struct SCA {
|
||||
UINT wDevID;
|
||||
UINT wMsg;
|
||||
DWORD_PTR dwParam1;
|
||||
DWORD_PTR dwParam2;
|
||||
};
|
||||
|
||||
/* EPP DWORD WINAPI mciSendCommandA(UINT wDevID, UINT wMsg, DWORD dwParam1, DWORD dwParam2); */
|
||||
|
||||
/**************************************************************************
|
||||
* MCI_SCAStarter [internal]
|
||||
*/
|
||||
static DWORD CALLBACK MCI_SCAStarter(LPVOID arg)
|
||||
{
|
||||
struct SCA* sca = arg;
|
||||
DWORD ret;
|
||||
|
||||
TRACE("In thread before async command (%08x,%u,%08lx,%08lx)\n",
|
||||
sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);
|
||||
ret = mciSendCommandA(sca->wDevID, sca->wMsg, sca->dwParam1 | MCI_WAIT, sca->dwParam2);
|
||||
TRACE("In thread after async command (%08x,%u,%08lx,%08lx)\n",
|
||||
sca->wDevID, sca->wMsg, sca->dwParam1, sca->dwParam2);
|
||||
HeapFree(GetProcessHeap(), 0, sca);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* MCI_SendCommandAsync [internal]
|
||||
*/
|
||||
static DWORD MCI_SendCommandAsync(UINT wDevID, UINT wMsg, DWORD_PTR dwParam1,
|
||||
DWORD_PTR dwParam2, UINT size)
|
||||
{
|
||||
HANDLE handle;
|
||||
struct SCA* sca = HeapAlloc(GetProcessHeap(), 0, sizeof(struct SCA) + size);
|
||||
|
||||
if (sca == 0)
|
||||
return MCIERR_OUT_OF_MEMORY;
|
||||
|
||||
sca->wDevID = wDevID;
|
||||
sca->wMsg = wMsg;
|
||||
sca->dwParam1 = dwParam1;
|
||||
|
||||
if (size && dwParam2) {
|
||||
sca->dwParam2 = (DWORD_PTR)sca + sizeof(struct SCA);
|
||||
/* copy structure passed by program in dwParam2 to be sure
|
||||
* we can still use it whatever the program does
|
||||
*/
|
||||
memcpy((LPVOID)sca->dwParam2, (LPVOID)dwParam2, size);
|
||||
} else {
|
||||
sca->dwParam2 = dwParam2;
|
||||
}
|
||||
|
||||
if ((handle = CreateThread(NULL, 0, MCI_SCAStarter, sca, 0, NULL)) == 0) {
|
||||
WARN("Couldn't allocate thread for async command handling, sending synchronously\n");
|
||||
return MCI_SCAStarter(sca);
|
||||
}
|
||||
SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
CloseHandle(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*======================================================================*
|
||||
* MCI MIDI implementation *
|
||||
*======================================================================*/
|
||||
|
||||
static DWORD mmr2mci(DWORD ret)
|
||||
{
|
||||
switch (ret) {
|
||||
case MMSYSERR_ALLOCATED:
|
||||
return MCIERR_SEQ_PORT_INUSE;
|
||||
case MMSYSERR_NOMEM:
|
||||
return MCIERR_OUT_OF_MEMORY;
|
||||
case MMSYSERR_BADDEVICEID: /* wine*.drv disabled */
|
||||
return MCIERR_SEQ_PORT_NONEXISTENT;
|
||||
case MIDIERR_INVALIDSETUP: /* from midimap.dll without snd-seq module */
|
||||
return MCIERR_SEQ_PORT_MAPNODEVICE;
|
||||
default:
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD MIDI_mciResume(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
|
||||
|
||||
/**************************************************************************
|
||||
@@ -233,8 +181,7 @@ static DWORD MIDI_mciReadByte(WINE_MCIMIDI* wmm, BYTE *lpbyt)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
|
||||
if (lpbyt == NULL ||
|
||||
mmioRead(wmm->hFile, (HPSTR)lpbyt, sizeof(BYTE)) != (long)sizeof(BYTE)) {
|
||||
if (mmioRead(wmm->hFile, (HPSTR)lpbyt, sizeof(BYTE)) != (long)sizeof(BYTE)) {
|
||||
WARN("Error reading wmm=%p\n", wmm);
|
||||
ret = MCIERR_INVALID_FILE;
|
||||
}
|
||||
@@ -250,8 +197,7 @@ static DWORD MIDI_mciReadWord(WINE_MCIMIDI* wmm, LPWORD lpw)
|
||||
BYTE hibyte, lobyte;
|
||||
DWORD ret = MCIERR_INVALID_FILE;
|
||||
|
||||
if (lpw != NULL &&
|
||||
MIDI_mciReadByte(wmm, &hibyte) == 0 &&
|
||||
if (MIDI_mciReadByte(wmm, &hibyte) == 0 &&
|
||||
MIDI_mciReadByte(wmm, &lobyte) == 0) {
|
||||
*lpw = ((WORD)hibyte << 8) + lobyte;
|
||||
ret = 0;
|
||||
@@ -267,8 +213,7 @@ static DWORD MIDI_mciReadLong(WINE_MCIMIDI* wmm, LPDWORD lpdw)
|
||||
WORD hiword, loword;
|
||||
DWORD ret = MCIERR_INVALID_FILE;
|
||||
|
||||
if (lpdw != NULL &&
|
||||
MIDI_mciReadWord(wmm, &hiword) == 0 &&
|
||||
if (MIDI_mciReadWord(wmm, &hiword) == 0 &&
|
||||
MIDI_mciReadWord(wmm, &loword) == 0) {
|
||||
*lpdw = MAKELONG(loword, hiword);
|
||||
ret = 0;
|
||||
@@ -283,24 +228,17 @@ static WORD MIDI_mciReadVaryLen(WINE_MCIMIDI* wmm, LPDWORD lpdw)
|
||||
{
|
||||
BYTE byte;
|
||||
DWORD value = 0;
|
||||
WORD ret = 0;
|
||||
WORD len = 0;
|
||||
|
||||
if (lpdw == NULL) {
|
||||
ret = MCIERR_INVALID_FILE;
|
||||
} else {
|
||||
do {
|
||||
if (MIDI_mciReadByte(wmm, &byte) != 0) {
|
||||
return 0;
|
||||
}
|
||||
value = (value << 7) + (byte & 0x7F);
|
||||
ret++;
|
||||
} while (byte & 0x80);
|
||||
*lpdw = value;
|
||||
/*
|
||||
TRACE("val=%08X\n", value);
|
||||
*/
|
||||
}
|
||||
return ret;
|
||||
do {
|
||||
if (MIDI_mciReadByte(wmm, &byte) != 0) {
|
||||
return 0;
|
||||
}
|
||||
value = (value << 7) + (byte & 0x7F);
|
||||
len++;
|
||||
} while (byte & 0x80);
|
||||
*lpdw = value;
|
||||
return len;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
@@ -411,10 +349,7 @@ static DWORD MIDI_mciReadMTrk(WINE_MCIMIDI* wmm, MCI_MIDITRACK* mmt)
|
||||
switch (LOWORD(mmt->dwEventData)) {
|
||||
case 0x02FF:
|
||||
case 0x03FF:
|
||||
/* position after meta data header */
|
||||
mmioSeek(wmm->hFile, mmt->dwIndex + HIWORD(mmt->dwEventData), SEEK_SET);
|
||||
len = mmt->wEventLength - HIWORD(mmt->dwEventData);
|
||||
|
||||
if (len >= sizeof(buf)) {
|
||||
WARN("Buffer for text is too small (%u are needed)\n", len);
|
||||
len = sizeof(buf) - 1;
|
||||
@@ -425,20 +360,20 @@ static DWORD MIDI_mciReadMTrk(WINE_MCIMIDI* wmm, MCI_MIDITRACK* mmt)
|
||||
case 0x02:
|
||||
if (wmm->lpstrCopyright) {
|
||||
WARN("Two copyright notices (%s|%s)\n", debugstr_w(wmm->lpstrCopyright), buf);
|
||||
} else {
|
||||
len = MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 );
|
||||
wmm->lpstrCopyright = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||
MultiByteToWideChar( CP_ACP, 0, buf, -1, wmm->lpstrCopyright, len );
|
||||
HeapFree(GetProcessHeap(), 0, wmm->lpstrCopyright);
|
||||
}
|
||||
len = MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 );
|
||||
wmm->lpstrCopyright = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||
MultiByteToWideChar( CP_ACP, 0, buf, -1, wmm->lpstrCopyright, len );
|
||||
break;
|
||||
case 0x03:
|
||||
if (wmm->lpstrName) {
|
||||
WARN("Two names (%s|%s)\n", debugstr_w(wmm->lpstrName), buf);
|
||||
} else {
|
||||
len = MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 );
|
||||
wmm->lpstrName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||
MultiByteToWideChar( CP_ACP, 0, buf, -1, wmm->lpstrName, len );
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, wmm->lpstrName);
|
||||
} /* last name or name from last track wins */
|
||||
len = MultiByteToWideChar( CP_ACP, 0, buf, -1, NULL, 0 );
|
||||
wmm->lpstrName = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
|
||||
MultiByteToWideChar( CP_ACP, 0, buf, -1, wmm->lpstrName, len );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -555,10 +490,10 @@ static DWORD MIDI_mciReadMThd(WINE_MCIMIDI* wmm, DWORD dwOffset)
|
||||
return MCIERR_INVALID_FILE;
|
||||
}
|
||||
|
||||
if (wmm->nTracks & 0x8000) {
|
||||
/* this shouldn't be a problem... */
|
||||
WARN("Ouch !! Implementation limitation to 32k tracks per MIDI file is overflowed\n");
|
||||
wmm->nTracks = 0x7FFF;
|
||||
if (wmm->nTracks > 0x80) {
|
||||
/* wTrackNr is 7 bits only */
|
||||
FIXME("Truncating MIDI file with %u tracks\n", wmm->nTracks);
|
||||
wmm->nTracks = 0x80;
|
||||
}
|
||||
|
||||
if ((wmm->tracks = HeapAlloc(GetProcessHeap(), 0, sizeof(MCI_MIDITRACK) * wmm->nTracks)) == NULL) {
|
||||
@@ -809,6 +744,10 @@ static DWORD MIDI_mciOpen(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_OPEN_PARMSW lp
|
||||
if (wmm->hFile != 0)
|
||||
mmioClose(wmm->hFile, 0);
|
||||
wmm->hFile = 0;
|
||||
HeapFree(GetProcessHeap(), 0, wmm->tracks);
|
||||
HeapFree(GetProcessHeap(), 0, wmm->lpstrElementName);
|
||||
HeapFree(GetProcessHeap(), 0, wmm->lpstrCopyright);
|
||||
HeapFree(GetProcessHeap(), 0, wmm->lpstrName);
|
||||
} else {
|
||||
wmm->dwPositionMS = 0;
|
||||
wmm->dwStatus = MCI_MODE_STOP;
|
||||
@@ -839,8 +778,8 @@ static DWORD MIDI_mciStop(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_GENERIC_PARMS
|
||||
if (oldstat == MCI_MODE_PAUSE)
|
||||
dwRet = midiOutReset((HMIDIOUT)wmm->hMidi);
|
||||
|
||||
while (wmm->dwStatus != MCI_MODE_STOP)
|
||||
Sleep(10);
|
||||
if ((dwFlags & MCI_WAIT) && wmm->hThread)
|
||||
WaitForSingleObject(wmm->hThread, INFINITE);
|
||||
}
|
||||
|
||||
/* sanity reset */
|
||||
@@ -871,6 +810,7 @@ static DWORD MIDI_mciClose(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_GENERIC_PARMS
|
||||
wmm->hFile = 0;
|
||||
TRACE("hFile closed !\n");
|
||||
}
|
||||
if (wmm->hThread) CloseHandle(wmm->hThread);
|
||||
HeapFree(GetProcessHeap(), 0, wmm->tracks);
|
||||
HeapFree(GetProcessHeap(), 0, wmm->lpstrElementName);
|
||||
HeapFree(GetProcessHeap(), 0, wmm->lpstrCopyright);
|
||||
@@ -911,55 +851,15 @@ static MCI_MIDITRACK* MIDI_mciFindNextEvent(WINE_MCIMIDI* wmm, LPDWORD hiPulse)
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* MIDI_mciPlay [internal]
|
||||
* MIDI_player [internal]
|
||||
*/
|
||||
static DWORD MIDI_mciPlay(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
|
||||
static DWORD MIDI_player(WINE_MCIMIDI* wmm, DWORD dwFlags)
|
||||
{
|
||||
DWORD dwStartMS, dwEndMS;
|
||||
DWORD dwRet = 0;
|
||||
DWORD dwRet;
|
||||
WORD doPlay, nt;
|
||||
MCI_MIDITRACK* mmt;
|
||||
DWORD hiPulse;
|
||||
HANDLE oldcb;
|
||||
|
||||
TRACE("(%d, %08X, %p);\n", wmm->wDevID, dwFlags, lpParms);
|
||||
|
||||
if (wmm->hFile == 0) {
|
||||
WARN("Can't play: no file %s!\n", debugstr_w(wmm->lpstrElementName));
|
||||
return MCIERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (wmm->dwStatus != MCI_MODE_STOP) {
|
||||
if (wmm->dwStatus == MCI_MODE_PAUSE) {
|
||||
/* FIXME: parameters (start/end) in lpParams may not be used */
|
||||
return MIDI_mciResume(wmm, dwFlags, (LPMCI_GENERIC_PARMS)lpParms);
|
||||
}
|
||||
WARN("Can't play: device is not stopped !\n");
|
||||
return MCIERR_INTERNAL;
|
||||
}
|
||||
|
||||
if (!(dwFlags & MCI_WAIT)) {
|
||||
return MCI_SendCommandAsync(wmm->wDevID, MCI_PLAY, dwFlags, (DWORD_PTR)lpParms, sizeof(MCI_PLAY_PARMS));
|
||||
}
|
||||
|
||||
if (lpParms && (dwFlags & MCI_FROM)) {
|
||||
dwStartMS = MIDI_ConvertTimeFormatToMS(wmm, lpParms->dwFrom);
|
||||
} else {
|
||||
dwStartMS = wmm->dwPositionMS;
|
||||
}
|
||||
|
||||
if (lpParms && (dwFlags & MCI_TO)) {
|
||||
dwEndMS = MIDI_ConvertTimeFormatToMS(wmm, lpParms->dwTo);
|
||||
} else {
|
||||
dwEndMS = 0xFFFFFFFFul;
|
||||
}
|
||||
|
||||
TRACE("Playing from %u to %u\n", dwStartMS, dwEndMS);
|
||||
|
||||
oldcb = InterlockedExchangePointer(&wmm->hCallback,
|
||||
(dwFlags & MCI_NOTIFY) ? HWND_32(LOWORD(lpParms->dwCallback)) : NULL);
|
||||
if (oldcb) mciDriverNotify(oldcb, wmm->wDevID, MCI_NOTIFY_ABORTED);
|
||||
oldcb = NULL;
|
||||
DWORD hiPulse, dwStartMS = wmm->dwPositionMS;
|
||||
HANDLE oldcb = NULL;
|
||||
|
||||
/* init tracks */
|
||||
for (nt = 0; nt < wmm->nTracks; nt++) {
|
||||
@@ -977,12 +877,11 @@ static DWORD MIDI_mciPlay(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_PLAY_PARMS lpP
|
||||
|
||||
dwRet = midiOutOpen((LPHMIDIOUT)&wmm->hMidi, wmm->wPort, 0L, 0L, CALLBACK_NULL);
|
||||
if (dwRet != MMSYSERR_NOERROR) {
|
||||
return dwRet;
|
||||
return mmr2mci(dwRet);
|
||||
}
|
||||
|
||||
wmm->dwPulse = 0;
|
||||
wmm->dwTempo = 500000;
|
||||
wmm->dwStatus = MCI_MODE_PLAY;
|
||||
wmm->dwPositionMS = 0;
|
||||
wmm->wStartedPlaying = FALSE;
|
||||
|
||||
@@ -992,7 +891,7 @@ static DWORD MIDI_mciPlay(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_PLAY_PARMS lpP
|
||||
*/
|
||||
while (((volatile WINE_MCIMIDI*)wmm)->dwStatus == MCI_MODE_PAUSE);
|
||||
|
||||
doPlay = (wmm->dwPositionMS >= dwStartMS && wmm->dwPositionMS <= dwEndMS);
|
||||
doPlay = (wmm->dwPositionMS >= dwStartMS && wmm->dwPositionMS <= wmm->dwEndMS);
|
||||
|
||||
TRACE("wmm->dwStatus=%d, doPlay=%c\n", wmm->dwStatus, doPlay ? 'T' : 'F');
|
||||
|
||||
@@ -1187,6 +1086,106 @@ static DWORD MIDI_mciPlay(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_PLAY_PARMS lpP
|
||||
/* Let the potentially asynchronous commands support FAILURE notification. */
|
||||
if (oldcb) mciDriverNotify(oldcb, wmm->wDevID,
|
||||
dwRet ? MCI_NOTIFY_FAILURE : MCI_NOTIFY_SUCCESSFUL);
|
||||
return mmr2mci(dwRet);
|
||||
}
|
||||
|
||||
static DWORD CALLBACK MIDI_Starter(void *ptr)
|
||||
{
|
||||
WINE_MCIMIDI* wmm = ptr;
|
||||
return MIDI_player(wmm, MCI_NOTIFY);
|
||||
}
|
||||
|
||||
static DWORD ensurePlayerThread(WINE_MCIMIDI* wmm)
|
||||
{
|
||||
if (1) {
|
||||
DWORD dwRet;
|
||||
|
||||
switch (wmm->dwStatus) {
|
||||
default:
|
||||
return MCIERR_NONAPPLICABLE_FUNCTION;
|
||||
case MCI_MODE_PAUSE:
|
||||
return MIDI_mciResume(wmm, 0, NULL);
|
||||
case MCI_MODE_PLAY:
|
||||
/* the player was not stopped, use it */
|
||||
return 0;
|
||||
case MCI_MODE_STOP:
|
||||
break;
|
||||
}
|
||||
wmm->dwStatus = MCI_MODE_PLAY;
|
||||
if (wmm->hThread) {
|
||||
WaitForSingleObject(wmm->hThread, INFINITE);
|
||||
CloseHandle(wmm->hThread);
|
||||
wmm->hThread = 0;
|
||||
}
|
||||
wmm->hThread = CreateThread(NULL, 0, MIDI_Starter, wmm, 0, NULL);
|
||||
if (!wmm->hThread) {
|
||||
dwRet = MCIERR_OUT_OF_MEMORY;
|
||||
} else {
|
||||
SetThreadPriority(wmm->hThread, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
dwRet = 0;
|
||||
}
|
||||
if (dwRet)
|
||||
wmm->dwStatus = MCI_MODE_STOP;
|
||||
return dwRet;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* MIDI_mciPlay [internal]
|
||||
*/
|
||||
static DWORD MIDI_mciPlay(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
|
||||
{
|
||||
DWORD dwStartMS, dwEndMS;
|
||||
DWORD dwRet;
|
||||
HANDLE oldcb;
|
||||
|
||||
TRACE("(%d, %08X, %p);\n", wmm->wDevID, dwFlags, lpParms);
|
||||
|
||||
if (wmm->hFile == 0) {
|
||||
WARN("Can't play: no file %s!\n", debugstr_w(wmm->lpstrElementName));
|
||||
return MCIERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (lpParms && (dwFlags & MCI_TO)) {
|
||||
dwEndMS = MIDI_ConvertTimeFormatToMS(wmm, lpParms->dwTo);
|
||||
/* FIXME: if (dwEndMS > length) return MCIERR_OUTOFRANGE; */
|
||||
} else {
|
||||
dwEndMS = 0xFFFFFFFFul; /* FIXME: dwEndMS = length; */
|
||||
}
|
||||
if (lpParms && (dwFlags & MCI_FROM)) {
|
||||
dwStartMS = MIDI_ConvertTimeFormatToMS(wmm, lpParms->dwFrom);
|
||||
} else {
|
||||
dwStartMS = wmm->dwPositionMS;
|
||||
}
|
||||
if (dwEndMS < dwStartMS)
|
||||
return MCIERR_OUTOFRANGE;
|
||||
|
||||
if (dwFlags & MCI_FROM) {
|
||||
/* Stop with MCI_NOTIFY_ABORTED and set new position. */
|
||||
MIDI_mciStop(wmm, MCI_WAIT, NULL);
|
||||
wmm->dwPositionMS = dwStartMS;
|
||||
} /* else use existing player. */
|
||||
if (wmm->dwEndMS != dwEndMS) {
|
||||
oldcb = InterlockedExchangePointer(&wmm->hCallback, NULL);
|
||||
if (oldcb) mciDriverNotify(oldcb, wmm->wDevID, MCI_NOTIFY_ABORTED);
|
||||
wmm->dwEndMS = dwEndMS;
|
||||
}
|
||||
|
||||
TRACE("Playing from %u to %u\n", dwStartMS, dwEndMS);
|
||||
|
||||
if ((dwFlags & MCI_NOTIFY) && lpParms) {
|
||||
oldcb = InterlockedExchangePointer(&wmm->hCallback, HWND_32(LOWORD(lpParms->dwCallback)));
|
||||
if (oldcb) mciDriverNotify(oldcb, wmm->wDevID, MCI_NOTIFY_SUPERSEDED);
|
||||
}
|
||||
|
||||
dwRet = ensurePlayerThread(wmm);
|
||||
|
||||
if (!dwRet && (dwFlags & MCI_WAIT)) {
|
||||
WaitForSingleObject(wmm->hThread, INFINITE);
|
||||
GetExitCodeThread(wmm->hThread, &dwRet);
|
||||
/* STATUS_PENDING cannot happen. It folds onto MCIERR_UNRECOGNIZED_KEYWORD */
|
||||
}
|
||||
/* The player thread performs notification at exit. */
|
||||
return dwRet;
|
||||
}
|
||||
|
||||
@@ -1331,13 +1330,14 @@ static DWORD MIDI_mciStatus(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_STATUS_PARMS
|
||||
case MCI_STATUS_LENGTH:
|
||||
if ((dwFlags & MCI_TRACK) && wmm->wFormat == 2) {
|
||||
if (lpParms->dwTrack >= wmm->nTracks)
|
||||
return MCIERR_BAD_INTEGER;
|
||||
return MCIERR_OUTOFRANGE;
|
||||
/* FIXME: this is wrong if there is a tempo change inside the file */
|
||||
lpParms->dwReturn = MIDI_ConvertPulseToMS(wmm, wmm->tracks[lpParms->dwTrack].dwLength);
|
||||
} else {
|
||||
lpParms->dwReturn = MIDI_GetMThdLengthMS(wmm);
|
||||
}
|
||||
lpParms->dwReturn = MIDI_ConvertMSToTimeFormat(wmm, lpParms->dwReturn);
|
||||
/* FIXME: ret = MCI_COLONIZED4_RETURN if SMPTE */
|
||||
TRACE("MCI_STATUS_LENGTH => %lu\n", lpParms->dwReturn);
|
||||
break;
|
||||
case MCI_STATUS_MODE:
|
||||
@@ -1355,9 +1355,10 @@ static DWORD MIDI_mciStatus(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_STATUS_PARMS
|
||||
TRACE("MCI_STATUS_NUMBER_OF_TRACKS => %lu\n", lpParms->dwReturn);
|
||||
break;
|
||||
case MCI_STATUS_POSITION:
|
||||
/* FIXME: do I need to use MCI_TRACK ? */
|
||||
/* FIXME: check MCI_TRACK == 1 if set */
|
||||
lpParms->dwReturn = MIDI_ConvertMSToTimeFormat(wmm,
|
||||
(dwFlags & MCI_STATUS_START) ? 0 : wmm->dwPositionMS);
|
||||
/* FIXME: ret = MCI_COLONIZED4_RETURN if SMPTE */
|
||||
TRACE("MCI_STATUS_POSITION %s => %lu\n",
|
||||
(dwFlags & MCI_STATUS_START) ? "start" : "current", lpParms->dwReturn);
|
||||
break;
|
||||
@@ -1375,7 +1376,7 @@ static DWORD MIDI_mciStatus(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_STATUS_PARMS
|
||||
case MCI_SEQ_STATUS_DIVTYPE:
|
||||
TRACE("MCI_SEQ_STATUS_DIVTYPE !\n");
|
||||
if (wmm->nDivision > 0x8000) {
|
||||
switch (wmm->nDivision) {
|
||||
switch (HIBYTE(wmm->nDivision)) {
|
||||
case 0xE8: lpParms->dwReturn = MCI_SEQ_DIV_SMPTE_24; break; /* -24 */
|
||||
case 0xE7: lpParms->dwReturn = MCI_SEQ_DIV_SMPTE_25; break; /* -25 */
|
||||
case 0xE3: lpParms->dwReturn = MCI_SEQ_DIV_SMPTE_30DROP; break; /* -29 */ /* is the MCI constant correct ? */
|
||||
@@ -1390,11 +1391,13 @@ static DWORD MIDI_mciStatus(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_STATUS_PARMS
|
||||
break;
|
||||
case MCI_SEQ_STATUS_MASTER:
|
||||
TRACE("MCI_SEQ_STATUS_MASTER !\n");
|
||||
lpParms->dwReturn = 0;
|
||||
lpParms->dwReturn = MAKEMCIRESOURCE(MCI_SEQ_NONE, MCI_SEQ_NONE_S);
|
||||
ret = MCI_RESOURCE_RETURNED;
|
||||
break;
|
||||
case MCI_SEQ_STATUS_SLAVE:
|
||||
TRACE("MCI_SEQ_STATUS_SLAVE !\n");
|
||||
lpParms->dwReturn = 0;
|
||||
lpParms->dwReturn = MAKEMCIRESOURCE(MCI_SEQ_FILE, MCI_SEQ_FILE_S);
|
||||
ret = MCI_RESOURCE_RETURNED;
|
||||
break;
|
||||
case MCI_SEQ_STATUS_OFFSET:
|
||||
TRACE("MCI_SEQ_STATUS_OFFSET !\n");
|
||||
@@ -1415,11 +1418,10 @@ static DWORD MIDI_mciStatus(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_STATUS_PARMS
|
||||
break;
|
||||
default:
|
||||
FIXME("Unknown command %08X !\n", lpParms->dwItem);
|
||||
return MCIERR_UNRECOGNIZED_COMMAND;
|
||||
return MCIERR_UNSUPPORTED_FUNCTION;
|
||||
}
|
||||
} else {
|
||||
WARN("No Status-Item!\n");
|
||||
return MCIERR_UNRECOGNIZED_COMMAND;
|
||||
return MCIERR_MISSING_PARAMETER;
|
||||
}
|
||||
if ((dwFlags & MCI_NOTIFY) && HRESULT_CODE(ret)==0)
|
||||
MIDI_mciNotify(lpParms->dwCallback, wmm, MCI_NOTIFY_SUCCESSFUL);
|
||||
@@ -1521,7 +1523,7 @@ static DWORD MIDI_mciInfo(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_INFO_PARMSW lp
|
||||
case MCI_INFO_NAME: str = wmm->lpstrName; break;
|
||||
default:
|
||||
WARN("Don't know this info command (%u)\n", dwFlags);
|
||||
return MCIERR_UNRECOGNIZED_COMMAND;
|
||||
return MCIERR_MISSING_PARAMETER; /* not MCIERR_FLAGS_... */
|
||||
}
|
||||
if (!ret) {
|
||||
if (lpParms->dwRetSize) {
|
||||
@@ -1541,32 +1543,32 @@ static DWORD MIDI_mciInfo(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_INFO_PARMSW lp
|
||||
*/
|
||||
static DWORD MIDI_mciSeek(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
DWORD position;
|
||||
|
||||
TRACE("(%d, %08X, %p);\n", wmm->wDevID, dwFlags, lpParms);
|
||||
|
||||
if (lpParms == NULL) {
|
||||
ret = MCIERR_NULL_PARAMETER_BLOCK;
|
||||
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
|
||||
|
||||
position = dwFlags & (MCI_SEEK_TO_START|MCI_SEEK_TO_END|MCI_TO);
|
||||
if (!position) return MCIERR_MISSING_PARAMETER;
|
||||
if (position&(position-1)) return MCIERR_FLAGS_NOT_COMPATIBLE;
|
||||
|
||||
MIDI_mciStop(wmm, MCI_WAIT, 0);
|
||||
|
||||
if (dwFlags & MCI_TO) { /* FIXME: compare with length */
|
||||
wmm->dwPositionMS = MIDI_ConvertTimeFormatToMS(wmm, lpParms->dwTo);
|
||||
} else if (dwFlags & MCI_SEEK_TO_START) {
|
||||
wmm->dwPositionMS = 0;
|
||||
} else {
|
||||
MIDI_mciStop(wmm, MCI_WAIT, 0);
|
||||
|
||||
if (dwFlags & MCI_SEEK_TO_START) {
|
||||
wmm->dwPositionMS = 0;
|
||||
} else if (dwFlags & MCI_SEEK_TO_END) {
|
||||
wmm->dwPositionMS = 0xFFFFFFFF; /* FIXME */
|
||||
} else if (dwFlags & MCI_TO) {
|
||||
wmm->dwPositionMS = MIDI_ConvertTimeFormatToMS(wmm, lpParms->dwTo);
|
||||
} else {
|
||||
WARN("dwFlag doesn't tell where to seek to...\n");
|
||||
return MCIERR_MISSING_PARAMETER;
|
||||
}
|
||||
|
||||
TRACE("Seeking to position=%u ms\n", wmm->dwPositionMS);
|
||||
|
||||
if (dwFlags & MCI_NOTIFY)
|
||||
MIDI_mciNotify(lpParms->dwCallback, wmm, MCI_NOTIFY_SUCCESSFUL);
|
||||
wmm->dwPositionMS = 0xFFFFFFFF; /* FIXME */
|
||||
}
|
||||
return ret;
|
||||
|
||||
TRACE("Seeking to position=%u ms\n", wmm->dwPositionMS);
|
||||
|
||||
if (dwFlags & MCI_NOTIFY)
|
||||
MIDI_mciNotify(lpParms->dwCallback, wmm, MCI_NOTIFY_SUCCESSFUL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*======================================================================*
|
||||
|
||||
@@ -100,7 +100,7 @@ reactos/dll/win32/mapi32 # Synced to Wine-1.7.1
|
||||
reactos/dll/win32/mciavi32 # Synced to Wine-1.7.1
|
||||
reactos/dll/win32/mcicda # Synced to Wine-1.5.19
|
||||
reactos/dll/win32/mciqtz32 # Synced to Wine-1.7.1
|
||||
reactos/dll/win32/mciseq # Synced to Wine-1.5.4
|
||||
reactos/dll/win32/mciseq # Synced to Wine-1.7.1
|
||||
reactos/dll/win32/mciwave # Synced to Wine-1.5.19
|
||||
reactos/dll/win32/mlang # Synced to Wine-1.5.4
|
||||
reactos/dll/win32/mpr # Autosync
|
||||
|
||||
Reference in New Issue
Block a user