=?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