=?UTF-8?Q?J=C3=B6rg=20H=C3=B6hle=20?=: mciseq: Create player thread in the synchronous case too.
Alexandre Julliard
julliard at winehq.org
Mon Oct 8 13:39:57 CDT 2012
Module: wine
Branch: master
Commit: 010019df064cfe1e9efee5ac6ee9e1e0954bd4f8
URL: http://source.winehq.org/git/wine.git/?a=commit;h=010019df064cfe1e9efee5ac6ee9e1e0954bd4f8
Author: Jörg Höhle <Joerg-Cyril.Hoehle at t-systems.com>
Date: Thu Oct 4 12:34:07 2012 +0200
mciseq: Create player thread in the synchronous case too.
---
dlls/mciseq/mcimidi.c | 156 +++++++++++++++++++++----------------------------
1 files changed, 66 insertions(+), 90 deletions(-)
diff --git a/dlls/mciseq/mcimidi.c b/dlls/mciseq/mcimidi.c
index 2a65027..e6927ac 100644
--- a/dlls/mciseq/mcimidi.c
+++ b/dlls/mciseq/mcimidi.c
@@ -62,6 +62,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;
@@ -77,79 +78,10 @@ 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 *
*======================================================================*/
@@ -831,8 +763,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 */
@@ -863,6 +795,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);
@@ -905,12 +838,12 @@ static MCI_MIDITRACK* MIDI_mciFindNextEvent(WINE_MCIMIDI* wmm, LPDWORD hiPulse)
/**************************************************************************
* MIDI_player [internal]
*/
-static DWORD MIDI_player(WINE_MCIMIDI* wmm, DWORD dwStartMS, DWORD dwEndMS, DWORD dwFlags)
+static DWORD MIDI_player(WINE_MCIMIDI* wmm, DWORD dwFlags)
{
DWORD dwRet;
WORD doPlay, nt;
MCI_MIDITRACK* mmt;
- DWORD hiPulse;
+ DWORD hiPulse, dwStartMS = wmm->dwPositionMS;
HANDLE oldcb = NULL;
/* init tracks */
@@ -934,7 +867,6 @@ static DWORD MIDI_player(WINE_MCIMIDI* wmm, DWORD dwStartMS, DWORD dwEndMS, DWOR
wmm->dwPulse = 0;
wmm->dwTempo = 500000;
- wmm->dwStatus = MCI_MODE_PLAY;
wmm->dwPositionMS = 0;
wmm->wStartedPlaying = FALSE;
@@ -944,7 +876,7 @@ static DWORD MIDI_player(WINE_MCIMIDI* wmm, DWORD dwStartMS, DWORD dwEndMS, DWOR
*/
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');
@@ -1142,12 +1074,54 @@ static DWORD MIDI_player(WINE_MCIMIDI* wmm, DWORD dwStartMS, DWORD dwEndMS, DWOR
return 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);
@@ -1157,19 +1131,6 @@ static DWORD MIDI_mciPlay(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_PLAY_PARMS lpP
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_TO)) {
dwEndMS = MIDI_ConvertTimeFormatToMS(wmm, lpParms->dwTo);
/* FIXME: if (dwEndMS > length) return MCIERR_OUTOFRANGE; */
@@ -1184,13 +1145,28 @@ static DWORD MIDI_mciPlay(WINE_MCIMIDI* wmm, DWORD dwFlags, LPMCI_PLAY_PARMS lpP
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. */
+ wmm->dwEndMS = dwEndMS;
+
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);
- return MIDI_player(wmm, dwStartMS, dwEndMS, dwFlags);
+ 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;
}
/**************************************************************************
More information about the wine-cvs
mailing list