diff --git a/dlls/mciavi32/mciavi.c b/dlls/mciavi32/mciavi.c index 597359c2028..079c6963eec 100644 --- a/dlls/mciavi32/mciavi.c +++ b/dlls/mciavi32/mciavi.c @@ -87,7 +87,6 @@ static DWORD MCIAVI_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp) InitializeCriticalSection(&wma->cs); wma->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINE_MCIAVI.cs"); - wma->ack_event = CreateEventW(NULL, FALSE, FALSE, NULL); wma->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL); wma->wDevID = modp->wDeviceID; wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0); @@ -121,7 +120,6 @@ static DWORD MCIAVI_drvClose(DWORD dwDevID) mciSetDriverData(dwDevID, 0); mciFreeCommandResource(wma->wCommandTable); - CloseHandle(wma->ack_event); CloseHandle(wma->hStopEvent); LeaveCriticalSection(&wma->cs); @@ -336,61 +334,6 @@ DWORD MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms) return dwRet; } -static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms); - -struct MCIAVI_play_data -{ - MCIDEVICEID wDevID; - DWORD flags; - MCI_PLAY_PARMS params; -}; - -/* - * MCIAVI_mciPlay_thread - * - * FIXME: probably should use a common worker thread created at the driver - * load time and queue all async commands to it. - */ -static DWORD WINAPI MCIAVI_mciPlay_thread(LPVOID arg) -{ - struct MCIAVI_play_data *data = (struct MCIAVI_play_data *)arg; - DWORD ret; - - TRACE("In thread before async play command (id %08x, flags %08x)\n", data->wDevID, data->flags); - ret = MCIAVI_mciPlay(data->wDevID, data->flags | MCI_WAIT, &data->params); - TRACE("In thread after async play command (id %08x, flags %08x)\n", data->wDevID, data->flags); - - HeapFree(GetProcessHeap(), 0, data); - return ret; -} - -/* - * MCIAVI_mciPlay_async - */ -static DWORD MCIAVI_mciPlay_async(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParams) -{ - HANDLE handle, ack_event = wma->ack_event; - struct MCIAVI_play_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct MCIAVI_play_data)); - - if (!data) return MCIERR_OUT_OF_MEMORY; - - data->wDevID = wma->wDevID; - data->flags = dwFlags; - data->params = *lpParams; - - if (!(handle = CreateThread(NULL, 0, MCIAVI_mciPlay_thread, data, 0, NULL))) - { - WARN("Couldn't create thread for async play, playing synchronously\n"); - return MCIAVI_mciPlay_thread(data); - } - SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL); - CloseHandle(handle); - /* wait until the thread starts up, so the app could see a changed status */ - WaitForSingleObject(ack_event, INFINITE); - TRACE("Async play has started\n"); - return 0; -} - static double currenttime_us(void) { LARGE_INTEGER lc, lf; @@ -400,90 +343,25 @@ static double currenttime_us(void) } /*************************************************************************** - * MCIAVI_mciPlay [internal] + * MCIAVI_player [internal] */ -static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) +static DWORD MCIAVI_player(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) { - WINE_MCIAVI *wma; DWORD dwRet; LPWAVEHDR waveHdr = NULL; unsigned i, nHdr = 0; - DWORD dwFromFrame, dwToFrame; DWORD numEvents = 1; HANDLE events[2]; double next_frame_us; - TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); - - if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; - - wma = MCIAVI_mciGetOpenDev(wDevID); - if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; - if (dwFlags & MCI_DGV_PLAY_REVERSE) return MCIERR_UNSUPPORTED_FUNCTION; - if (dwFlags & MCI_TEST) return 0; - EnterCriticalSection(&wma->cs); - if (!wma->hFile) - { - LeaveCriticalSection(&wma->cs); - return MCIERR_FILE_NOT_FOUND; - } - if (!wma->hWndPaint) - { - LeaveCriticalSection(&wma->cs); - return MCIERR_NO_WINDOW; - } - - LeaveCriticalSection(&wma->cs); - - if (!(dwFlags & MCI_WAIT)) - return MCIAVI_mciPlay_async(wma, dwFlags, lpParms); - - if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE)) - ShowWindow(wma->hWndPaint, SW_SHOWNA); - - EnterCriticalSection(&wma->cs); - - dwFromFrame = wma->dwCurrVideoFrame; - dwToFrame = wma->dwPlayableVideoFrames - 1; - - if (dwFlags & MCI_FROM) { - dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom); - } - if (dwFlags & MCI_TO) { - dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo); - } - if (dwToFrame >= wma->dwPlayableVideoFrames) - dwToFrame = wma->dwPlayableVideoFrames - 1; - - TRACE("Playing from frame=%u to frame=%u\n", dwFromFrame, dwToFrame); - - wma->dwCurrVideoFrame = dwFromFrame; - wma->dwToVideoFrame = dwToFrame; - - /* if already playing exit */ - if (wma->dwStatus == MCI_MODE_PLAY) - { - LeaveCriticalSection(&wma->cs); - SetEvent(wma->ack_event); - return 0; - } - if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame) { dwRet = 0; - SetEvent(wma->ack_event); goto mci_play_done; } - wma->dwStatus = MCI_MODE_PLAY; - /* signal the state change */ - SetEvent(wma->ack_event); - - if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN)) - FIXME("Unsupported flag %08x\n", dwFlags); - events[0] = wma->hStopEvent; if (wma->lpWaveFormat) { if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0) @@ -513,7 +391,7 @@ static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0; if (hDC) { - while(next_frame_us <= tc && wma->dwCurrVideoFrame < dwToFrame){ + while(next_frame_us <= tc && wma->dwCurrVideoFrame < wma->dwToVideoFrame){ double dur; ++wma->dwCurrVideoFrame; dur = MCIAVI_PaintFrame(wma, hDC); @@ -524,7 +402,7 @@ static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms } ReleaseDC(wma->hWndPaint, hDC); } - if(wma->dwCurrVideoFrame >= dwToFrame) + if(wma->dwCurrVideoFrame >= wma->dwToVideoFrame) break; if (wma->lpWaveFormat) @@ -579,12 +457,145 @@ mci_play_done: if (dwFlags & MCI_NOTIFY) { TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback); mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)), - wDevID, MCI_NOTIFY_SUCCESSFUL); + wma->wDevID, MCI_NOTIFY_SUCCESSFUL); } LeaveCriticalSection(&wma->cs); return dwRet; } +struct MCIAVI_play_data +{ + WINE_MCIAVI *wma; + DWORD flags; + MCI_PLAY_PARMS params; /* FIXME: notify via wma->hCallback like the other MCI drivers */ +}; + +/* + * MCIAVI_mciPlay_thread + * + * FIXME: probably should use a common worker thread created at the driver + * load time and queue all async commands to it. + */ +static DWORD WINAPI MCIAVI_mciPlay_thread(LPVOID arg) +{ + struct MCIAVI_play_data *data = (struct MCIAVI_play_data *)arg; + DWORD ret; + + TRACE("In thread before async play command (id %u, flags %08x)\n", data->wma->wDevID, data->flags); + ret = MCIAVI_player(data->wma, data->flags, &data->params); + TRACE("In thread after async play command (id %u, flags %08x)\n", data->wma->wDevID, data->flags); + + HeapFree(GetProcessHeap(), 0, data); + return ret; +} + +/* + * MCIAVI_mciPlay_async + */ +static DWORD MCIAVI_mciPlay_async(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParams) +{ + HANDLE handle; + struct MCIAVI_play_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct MCIAVI_play_data)); + + if (!data) return MCIERR_OUT_OF_MEMORY; + + data->wma = wma; + data->flags = dwFlags; + if (dwFlags & MCI_NOTIFY) + data->params.dwCallback = lpParams->dwCallback; + + if (!(handle = CreateThread(NULL, 0, MCIAVI_mciPlay_thread, data, 0, NULL))) + { + WARN("Couldn't create thread for async play, playing synchronously\n"); + return MCIAVI_mciPlay_thread(data); + } + SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL); + CloseHandle(handle); + return 0; +} + +/*************************************************************************** + * MCIAVI_mciPlay [internal] + */ +static DWORD MCIAVI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms) +{ + WINE_MCIAVI *wma; + DWORD dwRet; + DWORD dwFromFrame, dwToFrame; + + TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms); + + if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK; + + wma = MCIAVI_mciGetOpenDev(wDevID); + if (wma == NULL) return MCIERR_INVALID_DEVICE_ID; + if (dwFlags & MCI_DGV_PLAY_REVERSE) return MCIERR_UNSUPPORTED_FUNCTION; + if (dwFlags & MCI_TEST) return 0; + + if (dwFlags & (MCI_DGV_PLAY_REPEAT|MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLSCREEN|MCI_MCIAVI_PLAY_FULLBY2)) + FIXME("Unsupported flag %08x\n", dwFlags); + + EnterCriticalSection(&wma->cs); + + if (!wma->hFile) + { + LeaveCriticalSection(&wma->cs); + return MCIERR_FILE_NOT_FOUND; + } + if (!wma->hWndPaint) + { + LeaveCriticalSection(&wma->cs); + return MCIERR_NO_WINDOW; + } + + dwFromFrame = wma->dwCurrVideoFrame; + dwToFrame = wma->dwPlayableVideoFrames - 1; + + if (dwFlags & MCI_FROM) { + dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom); + } + if (dwFlags & MCI_TO) { + dwToFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo); + } + if (dwToFrame >= wma->dwPlayableVideoFrames) + dwToFrame = wma->dwPlayableVideoFrames - 1; + + TRACE("Playing from frame=%u to frame=%u\n", dwFromFrame, dwToFrame); + + wma->dwCurrVideoFrame = dwFromFrame; + wma->dwToVideoFrame = dwToFrame; + + LeaveCriticalSection(&wma->cs); + + if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE)) + ShowWindow(wma->hWndPaint, SW_SHOWNA); + + EnterCriticalSection(&wma->cs); + + /* if already playing exit */ + if (wma->dwStatus == MCI_MODE_PLAY) + { + LeaveCriticalSection(&wma->cs); + return 0; + } + + wma->dwStatus = MCI_MODE_PLAY; + + LeaveCriticalSection(&wma->cs); + + if (dwFlags & MCI_WAIT) + return MCIAVI_player(wma, dwFlags, lpParms); + + dwRet = MCIAVI_mciPlay_async(wma, dwFlags, lpParms); + + if (dwRet) { + EnterCriticalSection(&wma->cs); + wma->dwStatus = MCI_MODE_STOP; + LeaveCriticalSection(&wma->cs); + } + return dwRet; +} + /*************************************************************************** * MCIAVI_mciStop [internal] */ diff --git a/dlls/mciavi32/private_mciavi.h b/dlls/mciavi32/private_mciavi.h index 2b9d6c26b7b..4dfcc091c59 100644 --- a/dlls/mciavi32/private_mciavi.h +++ b/dlls/mciavi32/private_mciavi.h @@ -79,7 +79,6 @@ typedef struct { /* data for the background mechanism */ CRITICAL_SECTION cs; HANDLE hStopEvent; - HANDLE ack_event; /* acknowledge that an async command has started */ } WINE_MCIAVI; extern HINSTANCE MCIAVI_hInstance DECLSPEC_HIDDEN;