2009-03-01 11:54:06 +00:00
|
|
|
/*
|
|
|
|
* Digital video MCI Wine Driver
|
|
|
|
*
|
|
|
|
* Copyright 1999, 2000 Eric POUECH
|
|
|
|
* Copyright 2003 Dmitry Timoshkov
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* TODO list :
|
|
|
|
* - handling of palettes
|
|
|
|
* - recording (which input devices ?), a cam recorder ?
|
|
|
|
* - lots of messages still need to be handled (cf FIXME)
|
|
|
|
* - synchronization between audio and video (especially for interleaved
|
|
|
|
* files)
|
|
|
|
* - robustness when reading file can be enhanced
|
2012-01-24 14:07:33 +00:00
|
|
|
* - reimplement the AVI handling part with avifile DLL because
|
|
|
|
* "open @1122334 type avivideo alias a" expects an AVIFile/Stream
|
|
|
|
* and MCI_DGV_SET|STATUS_SPEED maps to Rate/Scale
|
2009-03-01 11:54:06 +00:00
|
|
|
* - some files appear to have more than one audio stream (we only play the
|
|
|
|
* first one)
|
|
|
|
* - some files contain an index of audio/video frame. Better use it,
|
2012-01-24 14:07:33 +00:00
|
|
|
* instead of rebuilding it (AVIFile does that already)
|
2009-03-01 11:54:06 +00:00
|
|
|
* - stopping while playing a file with sound blocks until all buffered
|
|
|
|
* audio is played... still should be stopped ASAP
|
|
|
|
*/
|
|
|
|
|
2018-03-17 12:17:07 +00:00
|
|
|
#include <string.h>
|
2009-03-01 11:54:06 +00:00
|
|
|
#include "private_mciavi.h"
|
2018-03-17 12:17:07 +00:00
|
|
|
#include "wine/debug.h"
|
2009-03-01 11:54:06 +00:00
|
|
|
|
2018-03-17 12:17:07 +00:00
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(mciavi);
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
static DWORD MCIAVI_mciStop(UINT, DWORD, LPMCI_GENERIC_PARMS);
|
|
|
|
|
|
|
|
/*======================================================================*
|
|
|
|
* MCI AVI implementation *
|
|
|
|
*======================================================================*/
|
|
|
|
|
|
|
|
HINSTANCE MCIAVI_hInstance = 0;
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* DllMain (MCIAVI.0)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
|
|
|
{
|
|
|
|
switch (fdwReason) {
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
DisableThreadLibraryCalls(hInstDLL);
|
|
|
|
MCIAVI_hInstance = hInstDLL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* MCIAVI_drvOpen [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_drvOpen(LPCWSTR str, LPMCI_OPEN_DRIVER_PARMSW modp)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI* wma;
|
|
|
|
static const WCHAR mciAviWStr[] = {'M','C','I','A','V','I',0};
|
|
|
|
|
|
|
|
TRACE("%s, %p\n", debugstr_w(str), modp);
|
|
|
|
|
|
|
|
/* session instance */
|
|
|
|
if (!modp) return 0xFFFFFFFF;
|
|
|
|
|
|
|
|
if (!MCIAVI_RegisterClass()) return 0;
|
|
|
|
|
|
|
|
wma = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCIAVI));
|
|
|
|
if (!wma)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
InitializeCriticalSection(&wma->cs);
|
|
|
|
wma->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": WINE_MCIAVI.cs");
|
|
|
|
wma->hStopEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
|
|
|
wma->wDevID = modp->wDeviceID;
|
|
|
|
wma->wCommandTable = mciLoadCommandResource(MCIAVI_hInstance, mciAviWStr, 0);
|
2010-04-20 17:16:57 +00:00
|
|
|
wma->dwStatus = MCI_MODE_NOT_READY;
|
2009-03-01 11:54:06 +00:00
|
|
|
modp->wCustomCommandTable = wma->wCommandTable;
|
|
|
|
modp->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
|
|
|
|
mciSetDriverData(wma->wDevID, (DWORD_PTR)wma);
|
|
|
|
|
|
|
|
return modp->wDeviceID;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* MCIAVI_drvClose [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_drvClose(DWORD dwDevID)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
TRACE("%04x\n", dwDevID);
|
|
|
|
|
|
|
|
/* finish all outstanding things */
|
|
|
|
MCIAVI_mciClose(dwDevID, MCI_WAIT, NULL);
|
|
|
|
|
|
|
|
wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
|
|
|
|
|
|
|
|
if (wma) {
|
|
|
|
MCIAVI_UnregisterClass();
|
|
|
|
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
mciSetDriverData(dwDevID, 0);
|
|
|
|
mciFreeCommandResource(wma->wCommandTable);
|
|
|
|
|
|
|
|
CloseHandle(wma->hStopEvent);
|
|
|
|
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
wma->cs.DebugInfo->Spare[0] = 0;
|
|
|
|
DeleteCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, wma);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return (dwDevID == 0xFFFFFFFF) ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* MCIAVI_drvConfigure [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_drvConfigure(DWORD dwDevID)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
TRACE("%04x\n", dwDevID);
|
|
|
|
|
|
|
|
MCIAVI_mciStop(dwDevID, MCI_WAIT, NULL);
|
|
|
|
|
|
|
|
wma = (WINE_MCIAVI*)mciGetDriverData(dwDevID);
|
|
|
|
|
|
|
|
if (wma) {
|
|
|
|
MessageBoxA(0, "Sample AVI Wine Driver !", "MM-Wine Driver", MB_OK);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* MCIAVI_mciGetOpenDev [internal]
|
|
|
|
*/
|
|
|
|
WINE_MCIAVI* MCIAVI_mciGetOpenDev(UINT wDevID)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI* wma = (WINE_MCIAVI*)mciGetDriverData(wDevID);
|
|
|
|
|
|
|
|
if (wma == NULL || wma->nUseCount == 0) {
|
|
|
|
WARN("Invalid wDevID=%u\n", wDevID);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return wma;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void MCIAVI_CleanUp(WINE_MCIAVI* wma)
|
|
|
|
{
|
|
|
|
/* to prevent handling in WindowProc */
|
|
|
|
wma->dwStatus = MCI_MODE_NOT_READY;
|
|
|
|
if (wma->hFile) {
|
|
|
|
mmioClose(wma->hFile, 0);
|
|
|
|
wma->hFile = 0;
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, wma->lpFileName);
|
|
|
|
wma->lpFileName = NULL;
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, wma->lpVideoIndex);
|
|
|
|
wma->lpVideoIndex = NULL;
|
|
|
|
HeapFree(GetProcessHeap(), 0, wma->lpAudioIndex);
|
|
|
|
wma->lpAudioIndex = NULL;
|
|
|
|
if (wma->hic) ICClose(wma->hic);
|
|
|
|
wma->hic = 0;
|
|
|
|
HeapFree(GetProcessHeap(), 0, wma->inbih);
|
|
|
|
wma->inbih = NULL;
|
|
|
|
HeapFree(GetProcessHeap(), 0, wma->outbih);
|
|
|
|
wma->outbih = NULL;
|
|
|
|
HeapFree(GetProcessHeap(), 0, wma->indata);
|
|
|
|
wma->indata = NULL;
|
|
|
|
HeapFree(GetProcessHeap(), 0, wma->outdata);
|
|
|
|
wma->outdata = NULL;
|
|
|
|
if (wma->hbmFrame) DeleteObject(wma->hbmFrame);
|
|
|
|
wma->hbmFrame = 0;
|
|
|
|
if (wma->hWnd) DestroyWindow(wma->hWnd);
|
|
|
|
wma->hWnd = 0;
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
|
|
|
|
wma->lpWaveFormat = 0;
|
|
|
|
|
|
|
|
memset(&wma->mah, 0, sizeof(wma->mah));
|
|
|
|
memset(&wma->ash_video, 0, sizeof(wma->ash_video));
|
|
|
|
memset(&wma->ash_audio, 0, sizeof(wma->ash_audio));
|
|
|
|
wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
|
|
|
|
wma->dwCachedFrame = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* MCIAVI_mciOpen [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciOpen(UINT wDevID, DWORD dwFlags,
|
|
|
|
LPMCI_DGV_OPEN_PARMSW lpOpenParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
LRESULT dwRet = 0;
|
|
|
|
|
|
|
|
TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpOpenParms);
|
|
|
|
|
|
|
|
if (lpOpenParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
|
|
|
|
|
|
|
|
wma = (WINE_MCIAVI *)mciGetDriverData(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
|
|
|
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
if (wma->nUseCount > 0) {
|
|
|
|
/* The driver is already open on this channel */
|
|
|
|
/* If the driver was opened shareable before and this open specifies */
|
|
|
|
/* shareable then increment the use count */
|
|
|
|
if (wma->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
|
|
|
|
++wma->nUseCount;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return MCIERR_MUST_USE_SHAREABLE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
wma->nUseCount = 1;
|
|
|
|
wma->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
wma->dwStatus = MCI_MODE_NOT_READY;
|
|
|
|
|
|
|
|
if (dwFlags & MCI_OPEN_ELEMENT) {
|
|
|
|
if (dwFlags & MCI_OPEN_ELEMENT_ID) {
|
|
|
|
/* could it be that (DWORD)lpOpenParms->lpstrElementName
|
|
|
|
* contains the hFile value ?
|
|
|
|
*/
|
|
|
|
dwRet = MCIERR_UNRECOGNIZED_COMMAND;
|
2010-03-10 16:21:22 +00:00
|
|
|
} else if (lpOpenParms->lpstrElementName && lpOpenParms->lpstrElementName[0]) {
|
2009-03-01 11:54:06 +00:00
|
|
|
/* FIXME : what should be done id wma->hFile is already != 0, or the driver is playin' */
|
|
|
|
TRACE("MCI_OPEN_ELEMENT %s!\n", debugstr_w(lpOpenParms->lpstrElementName));
|
|
|
|
|
2019-11-09 20:51:26 +00:00
|
|
|
wma->lpFileName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(lpOpenParms->lpstrElementName) + 1) * sizeof(WCHAR));
|
|
|
|
lstrcpyW(wma->lpFileName, lpOpenParms->lpstrElementName);
|
2010-03-10 16:21:22 +00:00
|
|
|
|
2012-01-24 14:07:33 +00:00
|
|
|
if (lpOpenParms->lpstrElementName[0] == '@') {
|
|
|
|
/* The file name @11223344 encodes an AVIFile handle in decimal notation
|
|
|
|
* in Win3.1 and w2k/NT, but this feature is absent in win95 (KB140750).
|
2019-11-09 20:51:26 +00:00
|
|
|
* wma->hFile = LongToHandle(wcstol(lpOpenParms->lpstrElementName+1, NULL, 10)); */
|
2012-01-24 14:07:33 +00:00
|
|
|
FIXME("Using AVIFile/Stream %s NIY\n", debugstr_w(lpOpenParms->lpstrElementName));
|
|
|
|
}
|
2010-03-10 16:21:22 +00:00
|
|
|
wma->hFile = mmioOpenW(lpOpenParms->lpstrElementName, NULL,
|
|
|
|
MMIO_ALLOCBUF | MMIO_DENYWRITE | MMIO_READ);
|
|
|
|
|
|
|
|
if (wma->hFile == 0) {
|
|
|
|
WARN("can't find file=%s!\n", debugstr_w(lpOpenParms->lpstrElementName));
|
|
|
|
dwRet = MCIERR_FILE_NOT_FOUND;
|
|
|
|
} else {
|
|
|
|
if (!MCIAVI_GetInfo(wma))
|
|
|
|
dwRet = MCIERR_INVALID_FILE;
|
|
|
|
else if (!MCIAVI_OpenVideo(wma))
|
|
|
|
dwRet = MCIERR_CANNOT_LOAD_DRIVER;
|
|
|
|
else if (!MCIAVI_CreateWindow(wma, dwFlags, lpOpenParms))
|
|
|
|
dwRet = MCIERR_CREATEWINDOW;
|
2009-03-01 11:54:06 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
FIXME("Don't record yet\n");
|
|
|
|
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dwRet == 0) {
|
|
|
|
TRACE("lpOpenParms->wDeviceID = %04x\n", lpOpenParms->wDeviceID);
|
|
|
|
|
|
|
|
wma->dwStatus = MCI_MODE_STOP;
|
|
|
|
wma->dwMciTimeFormat = MCI_FORMAT_FRAMES;
|
|
|
|
} else {
|
|
|
|
MCIAVI_CleanUp(wma);
|
|
|
|
}
|
|
|
|
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
|
|
|
|
if (!dwRet && (dwFlags & MCI_NOTIFY)) {
|
|
|
|
mciDriverNotify(HWND_32(LOWORD(lpOpenParms->dwCallback)),
|
|
|
|
wDevID, MCI_NOTIFY_SUCCESSFUL);
|
|
|
|
}
|
2009-03-01 11:54:06 +00:00
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* MCIAVI_mciClose [internal]
|
|
|
|
*/
|
|
|
|
DWORD MCIAVI_mciClose(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
DWORD dwRet = 0;
|
|
|
|
|
|
|
|
TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
|
|
|
|
|
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
|
|
|
|
2010-04-20 17:16:57 +00:00
|
|
|
MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
|
|
|
|
|
2009-03-01 11:54:06 +00:00
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
if (wma->nUseCount == 1) {
|
|
|
|
MCIAVI_CleanUp(wma);
|
|
|
|
|
|
|
|
if ((dwFlags & MCI_NOTIFY) && lpParms) {
|
|
|
|
mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
|
|
|
|
wDevID,
|
|
|
|
MCI_NOTIFY_SUCCESSFUL);
|
|
|
|
}
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
wma->nUseCount--;
|
|
|
|
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
|
2013-09-21 12:57:03 +00:00
|
|
|
static double currenttime_us(void)
|
|
|
|
{
|
|
|
|
LARGE_INTEGER lc, lf;
|
|
|
|
QueryPerformanceCounter(&lc);
|
|
|
|
QueryPerformanceFrequency(&lf);
|
|
|
|
return (lc.QuadPart * 1000000) / lf.QuadPart;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* MCIAVI_player [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_player(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
|
|
|
|
{
|
|
|
|
DWORD dwRet;
|
|
|
|
LPWAVEHDR waveHdr = NULL;
|
|
|
|
unsigned i, nHdr = 0;
|
|
|
|
DWORD numEvents = 1;
|
|
|
|
HANDLE events[2];
|
|
|
|
double next_frame_us;
|
2017-06-03 22:28:56 +00:00
|
|
|
BOOL wait_audio = TRUE;
|
2013-09-21 12:57:03 +00:00
|
|
|
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
if (wma->dwToVideoFrame <= wma->dwCurrVideoFrame)
|
|
|
|
{
|
|
|
|
dwRet = 0;
|
|
|
|
goto mci_play_done;
|
|
|
|
}
|
|
|
|
|
|
|
|
events[0] = wma->hStopEvent;
|
|
|
|
if (wma->lpWaveFormat) {
|
|
|
|
if (MCIAVI_OpenAudio(wma, &nHdr, &waveHdr) != 0)
|
|
|
|
{
|
|
|
|
/* can't play audio */
|
|
|
|
HeapFree(GetProcessHeap(), 0, wma->lpWaveFormat);
|
|
|
|
wma->lpWaveFormat = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* fill the queue with as many wave headers as possible */
|
|
|
|
MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
|
|
|
|
events[1] = wma->hEvent;
|
|
|
|
numEvents = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
next_frame_us = currenttime_us();
|
|
|
|
while (wma->dwStatus == MCI_MODE_PLAY)
|
|
|
|
{
|
|
|
|
HDC hDC;
|
|
|
|
double tc, delta;
|
|
|
|
DWORD ret;
|
|
|
|
|
|
|
|
tc = currenttime_us();
|
|
|
|
|
|
|
|
hDC = wma->hWndPaint ? GetDC(wma->hWndPaint) : 0;
|
|
|
|
if (hDC)
|
|
|
|
{
|
|
|
|
while(next_frame_us <= tc && wma->dwCurrVideoFrame < wma->dwToVideoFrame){
|
|
|
|
double dur;
|
|
|
|
dur = MCIAVI_PaintFrame(wma, hDC);
|
2015-11-21 09:25:00 +00:00
|
|
|
++wma->dwCurrVideoFrame;
|
2013-09-21 12:57:03 +00:00
|
|
|
if(!dur)
|
|
|
|
break;
|
|
|
|
next_frame_us += dur;
|
|
|
|
TRACE("next_frame: %f\n", next_frame_us);
|
|
|
|
}
|
|
|
|
ReleaseDC(wma->hWndPaint, hDC);
|
|
|
|
}
|
2015-11-21 09:25:00 +00:00
|
|
|
if (wma->dwCurrVideoFrame >= wma->dwToVideoFrame)
|
|
|
|
{
|
|
|
|
if (!(dwFlags & MCI_DGV_PLAY_REPEAT))
|
|
|
|
break;
|
|
|
|
TRACE("repeat media as requested\n");
|
|
|
|
wma->dwCurrVideoFrame = wma->dwCurrAudioBlock = 0;
|
|
|
|
}
|
2013-09-21 12:57:03 +00:00
|
|
|
|
|
|
|
if (wma->lpWaveFormat)
|
|
|
|
MCIAVI_PlayAudioBlocks(wma, nHdr, waveHdr);
|
|
|
|
|
|
|
|
tc = currenttime_us();
|
2015-11-21 09:25:00 +00:00
|
|
|
if (tc < next_frame_us)
|
2013-09-21 12:57:03 +00:00
|
|
|
delta = next_frame_us - tc;
|
|
|
|
else
|
|
|
|
delta = 0;
|
|
|
|
|
2017-06-03 22:28:56 +00:00
|
|
|
/* check if the playback was cancelled */
|
|
|
|
if ((wma->mci_break.flags & MCI_BREAK_KEY) &&
|
|
|
|
(GetAsyncKeyState(wma->mci_break.parms.nVirtKey) & 0x8000))
|
|
|
|
{
|
|
|
|
if (!(wma->mci_break.flags & MCI_BREAK_HWND) ||
|
|
|
|
GetForegroundWindow() == wma->mci_break.parms.hwndBreak)
|
|
|
|
{
|
|
|
|
/* we queue audio blocks ahead so ignore them otherwise the audio
|
|
|
|
* will keep playing until the buffer is empty */
|
|
|
|
wait_audio = FALSE;
|
|
|
|
|
|
|
|
TRACE("playback cancelled using break key\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-21 12:57:03 +00:00
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
ret = WaitForMultipleObjects(numEvents, events, FALSE, delta / 1000);
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
if (ret == WAIT_OBJECT_0 || wma->dwStatus != MCI_MODE_PLAY) break;
|
|
|
|
}
|
|
|
|
|
2017-06-03 22:28:56 +00:00
|
|
|
if (wma->lpWaveFormat)
|
|
|
|
{
|
|
|
|
if (wait_audio)
|
|
|
|
while (wma->dwEventCount != nHdr - 1)
|
|
|
|
{
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
Sleep(100);
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
}
|
2013-09-21 12:57:03 +00:00
|
|
|
|
|
|
|
/* just to get rid of some race conditions between play, stop and pause */
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
waveOutReset(wma->hWave);
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
for (i = 0; i < nHdr; i++)
|
|
|
|
waveOutUnprepareHeader(wma->hWave, &waveHdr[i], sizeof(WAVEHDR));
|
|
|
|
}
|
|
|
|
|
|
|
|
dwRet = 0;
|
|
|
|
|
|
|
|
if (wma->lpWaveFormat) {
|
|
|
|
HeapFree(GetProcessHeap(), 0, waveHdr);
|
|
|
|
|
|
|
|
if (wma->hWave) {
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
waveOutClose(wma->hWave);
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
wma->hWave = 0;
|
|
|
|
}
|
|
|
|
CloseHandle(wma->hEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
mci_play_done:
|
|
|
|
wma->dwStatus = MCI_MODE_STOP;
|
|
|
|
|
|
|
|
if (dwFlags & MCI_NOTIFY) {
|
|
|
|
TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
|
|
|
|
mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
|
|
|
|
wma->wDevID, MCI_NOTIFY_SUCCESSFUL);
|
|
|
|
}
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return dwRet;
|
|
|
|
}
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
struct MCIAVI_play_data
|
|
|
|
{
|
2013-09-21 12:57:03 +00:00
|
|
|
WINE_MCIAVI *wma;
|
2009-03-01 11:54:06 +00:00
|
|
|
DWORD flags;
|
2013-09-21 12:57:03 +00:00
|
|
|
MCI_PLAY_PARMS params; /* FIXME: notify via wma->hCallback like the other MCI drivers */
|
2009-03-01 11:54:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
|
2013-09-21 12:57:03 +00:00
|
|
|
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);
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, data);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* MCIAVI_mciPlay_async
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciPlay_async(WINE_MCIAVI *wma, DWORD dwFlags, LPMCI_PLAY_PARMS lpParams)
|
|
|
|
{
|
2013-09-21 12:57:03 +00:00
|
|
|
HANDLE handle;
|
2009-03-01 11:54:06 +00:00
|
|
|
struct MCIAVI_play_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(struct MCIAVI_play_data));
|
|
|
|
|
|
|
|
if (!data) return MCIERR_OUT_OF_MEMORY;
|
|
|
|
|
2013-09-21 12:57:03 +00:00
|
|
|
data->wma = wma;
|
2009-03-01 11:54:06 +00:00
|
|
|
data->flags = dwFlags;
|
2013-09-21 12:57:03 +00:00
|
|
|
if (dwFlags & MCI_NOTIFY)
|
|
|
|
data->params.dwCallback = lpParams->dwCallback;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
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;
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_DGV_PLAY_REVERSE) return MCIERR_UNSUPPORTED_FUNCTION;
|
|
|
|
if (dwFlags & MCI_TEST) return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
2019-11-09 20:51:26 +00:00
|
|
|
if (dwFlags & (MCI_MCIAVI_PLAY_WINDOW|MCI_MCIAVI_PLAY_FULLBY2))
|
2013-09-21 12:57:03 +00:00
|
|
|
FIXME("Unsupported flag %08x\n", dwFlags);
|
|
|
|
|
2009-03-01 11:54:06 +00:00
|
|
|
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;
|
|
|
|
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
if (dwFlags & MCI_FROM) {
|
2009-03-01 11:54:06 +00:00
|
|
|
dwFromFrame = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwFrom);
|
|
|
|
}
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
if (dwFlags & MCI_TO) {
|
2009-03-01 11:54:06 +00:00
|
|
|
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;
|
|
|
|
|
2013-09-21 12:57:03 +00:00
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
|
2019-11-09 20:51:26 +00:00
|
|
|
if (dwFlags & MCI_MCIAVI_PLAY_FULLSCREEN)
|
|
|
|
{
|
|
|
|
HMONITOR mon = MonitorFromWindow(wma->hWndPaint, MONITOR_DEFAULTTONEAREST);
|
|
|
|
MONITORINFO mi;
|
|
|
|
mi.cbSize = sizeof(mi);
|
|
|
|
GetMonitorInfoA(mon, &mi);
|
|
|
|
wma->hWndPaint = CreateWindowA("STATIC", NULL, WS_POPUP | WS_VISIBLE, mi.rcMonitor.left,
|
|
|
|
mi.rcMonitor.top, mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top,
|
|
|
|
NULL, NULL, NULL, 0);
|
|
|
|
}
|
|
|
|
/* if not fullscreen ensure the window is visible */
|
|
|
|
else if (!(GetWindowLongW(wma->hWndPaint, GWL_STYLE) & WS_VISIBLE))
|
2013-09-21 12:57:03 +00:00
|
|
|
ShowWindow(wma->hWndPaint, SW_SHOWNA);
|
|
|
|
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
2009-03-01 11:54:06 +00:00
|
|
|
/* if already playing exit */
|
|
|
|
if (wma->dwStatus == MCI_MODE_PLAY)
|
|
|
|
{
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
wma->dwStatus = MCI_MODE_PLAY;
|
|
|
|
|
2013-09-21 12:57:03 +00:00
|
|
|
LeaveCriticalSection(&wma->cs);
|
2009-03-01 11:54:06 +00:00
|
|
|
|
2013-09-21 12:57:03 +00:00
|
|
|
if (dwFlags & MCI_WAIT)
|
|
|
|
return MCIAVI_player(wma, dwFlags, lpParms);
|
2009-03-01 11:54:06 +00:00
|
|
|
|
2013-09-21 12:57:03 +00:00
|
|
|
dwRet = MCIAVI_mciPlay_async(wma, dwFlags, lpParms);
|
2009-03-01 11:54:06 +00:00
|
|
|
|
2013-09-21 12:57:03 +00:00
|
|
|
if (dwRet) {
|
2009-03-01 11:54:06 +00:00
|
|
|
EnterCriticalSection(&wma->cs);
|
2013-09-21 12:57:03 +00:00
|
|
|
wma->dwStatus = MCI_MODE_STOP;
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
2009-03-01 11:54:06 +00:00
|
|
|
}
|
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* MCIAVI_mciStop [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
DWORD dwRet = 0;
|
|
|
|
|
|
|
|
TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
|
|
|
|
|
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_TEST) return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
TRACE("current status %04x\n", wma->dwStatus);
|
|
|
|
|
|
|
|
switch (wma->dwStatus) {
|
|
|
|
case MCI_MODE_PLAY:
|
|
|
|
case MCI_MODE_RECORD:
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
SetEvent(wma->hStopEvent);
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
/* fall through */
|
|
|
|
case MCI_MODE_PAUSE:
|
|
|
|
/* Since our wave notification callback takes the lock,
|
|
|
|
* we must release it before resetting the device */
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
dwRet = waveOutReset(wma->hWave);
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
/* fall through */
|
|
|
|
default:
|
|
|
|
do /* one more chance for an async thread to finish */
|
|
|
|
{
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
Sleep(10);
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
} while (wma->dwStatus != MCI_MODE_STOP);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case MCI_MODE_NOT_READY:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((dwFlags & MCI_NOTIFY) && lpParms) {
|
|
|
|
mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
|
|
|
|
wDevID, MCI_NOTIFY_SUCCESSFUL);
|
|
|
|
}
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* MCIAVI_mciPause [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
|
|
|
|
|
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_TEST) return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
if (wma->dwStatus == MCI_MODE_PLAY)
|
|
|
|
wma->dwStatus = MCI_MODE_PAUSE;
|
|
|
|
|
|
|
|
if (wma->lpWaveFormat) {
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return waveOutPause(wma->hWave);
|
|
|
|
}
|
|
|
|
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* MCIAVI_mciResume [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
TRACE("(%04x, %08X, %p)\n", wDevID, dwFlags, lpParms);
|
|
|
|
|
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_TEST) return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
if (wma->dwStatus == MCI_MODE_PAUSE)
|
|
|
|
wma->dwStatus = MCI_MODE_PLAY;
|
|
|
|
|
|
|
|
if (wma->lpWaveFormat) {
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return waveOutRestart(wma->hWave);
|
|
|
|
}
|
|
|
|
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* MCIAVI_mciSeek [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
2010-03-10 16:21:22 +00:00
|
|
|
DWORD position;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2010-03-10 16:21:22 +00:00
|
|
|
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;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_TO) {
|
|
|
|
position = MCIAVI_ConvertTimeFormatToFrame(wma, lpParms->dwTo);
|
|
|
|
if (position >= wma->dwPlayableVideoFrames)
|
|
|
|
return MCIERR_OUTOFRANGE;
|
|
|
|
} else if (dwFlags & MCI_SEEK_TO_START) {
|
|
|
|
position = 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
} else {
|
2010-03-10 16:21:22 +00:00
|
|
|
position = wma->dwPlayableVideoFrames - 1;
|
2009-03-01 11:54:06 +00:00
|
|
|
}
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_TEST) return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
2010-03-10 16:21:22 +00:00
|
|
|
MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
|
|
|
|
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
wma->dwCurrVideoFrame = position;
|
|
|
|
TRACE("Seeking to frame=%u\n", wma->dwCurrVideoFrame);
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
if (dwFlags & MCI_NOTIFY) {
|
|
|
|
mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
|
|
|
|
wDevID, MCI_NOTIFY_SUCCESSFUL);
|
|
|
|
}
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
* MCIAVI_mciLoad [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciLoad(UINT wDevID, DWORD dwFlags, LPMCI_DGV_LOAD_PARMSW lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
|
|
|
|
|
|
|
|
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
|
|
|
|
|
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
|
|
|
|
2010-03-10 16:21:22 +00:00
|
|
|
return MCIERR_UNSUPPORTED_FUNCTION; /* like w2k */
|
2009-03-01 11:54:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* MCIAVI_mciRealize [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciRealize(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
|
|
|
|
|
|
|
|
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
|
|
|
|
|
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_TEST) return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* MCIAVI_mciUpdate [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciUpdate(UINT wDevID, DWORD dwFlags, LPMCI_DGV_UPDATE_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
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;
|
2010-03-10 16:21:22 +00:00
|
|
|
/* Ignore MCI_TEST flag. */
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
if (dwFlags & MCI_DGV_UPDATE_HDC)
|
|
|
|
MCIAVI_PaintFrame(wma, lpParms->hDC);
|
|
|
|
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* MCIAVI_mciStep [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciStep(UINT wDevID, DWORD dwFlags, LPMCI_DGV_STEP_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
2010-03-10 16:21:22 +00:00
|
|
|
DWORD position;
|
|
|
|
int delta = 1;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
2010-03-10 16:21:22 +00:00
|
|
|
TRACE("(%04x, %08x, %p)\n", wDevID, dwFlags, lpParms);
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
|
|
|
|
|
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
|
|
|
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_DGV_STEP_FRAMES) delta = lpParms->dwFrames;
|
|
|
|
if (dwFlags & MCI_DGV_STEP_REVERSE) delta = -delta;
|
|
|
|
position = wma->dwCurrVideoFrame + delta;
|
|
|
|
if (position >= wma->dwPlayableVideoFrames) return MCIERR_OUTOFRANGE;
|
|
|
|
if (dwFlags & MCI_TEST) return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
MCIAVI_mciStop(wDevID, MCI_WAIT, NULL);
|
|
|
|
|
2010-03-10 16:21:22 +00:00
|
|
|
EnterCriticalSection(&wma->cs);
|
2009-03-01 11:54:06 +00:00
|
|
|
|
2010-03-10 16:21:22 +00:00
|
|
|
wma->dwCurrVideoFrame = position;
|
|
|
|
TRACE("Stepping to frame=%u\n", wma->dwCurrVideoFrame);
|
2009-03-01 11:54:06 +00:00
|
|
|
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_NOTIFY) {
|
|
|
|
mciDriverNotify(HWND_32(LOWORD(lpParms->dwCallback)),
|
|
|
|
wDevID, MCI_NOTIFY_SUCCESSFUL);
|
|
|
|
}
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
2009-03-01 11:54:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* MCIAVI_mciCue [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciCue(UINT wDevID, DWORD dwFlags, LPMCI_DGV_CUE_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
|
|
|
|
|
|
|
|
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
|
|
|
|
|
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_DGV_CUE_INPUT) return MCIERR_UNSUPPORTED_FUNCTION;
|
|
|
|
if (dwFlags & MCI_TEST) return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-06-03 22:28:56 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* MCIAVI_mciBreak [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciBreak(UINT wDevID, DWORD dwFlags, LPMCI_BREAK_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
EnterCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
wma->mci_break.flags = dwFlags;
|
|
|
|
wma->mci_break.parms = *lpParms;
|
|
|
|
|
|
|
|
LeaveCriticalSection(&wma->cs);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-03-01 11:54:06 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* MCIAVI_mciSetAudio [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciSetAudio(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMSW lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
|
|
|
|
|
2010-04-20 17:16:57 +00:00
|
|
|
FIXME("(%04x, %08x, %p) Item %04x: stub\n", wDevID, dwFlags, lpParms, dwFlags & MCI_DGV_SETAUDIO_ITEM ? lpParms->dwItem : 0);
|
|
|
|
|
2009-03-01 11:54:06 +00:00
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
|
|
|
|
2010-04-20 17:16:57 +00:00
|
|
|
return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* MCIAVI_mciSignal [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciSignal(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SIGNAL_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
|
|
|
|
|
|
|
|
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
|
|
|
|
|
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* MCIAVI_mciSetVideo [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciSetVideo(UINT wDevID, DWORD dwFlags, LPMCI_DGV_SETVIDEO_PARMSW lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
|
|
|
|
|
2010-04-20 17:16:57 +00:00
|
|
|
FIXME("(%04x, %08x, %p) Item %04x: stub\n", wDevID, dwFlags, lpParms, dwFlags & MCI_DGV_SETVIDEO_ITEM ? lpParms->dwItem : 0);
|
|
|
|
|
2009-03-01 11:54:06 +00:00
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
|
|
|
|
2010-04-20 17:16:57 +00:00
|
|
|
return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* MCIAVI_mciConfigure [internal]
|
|
|
|
*/
|
|
|
|
static DWORD MCIAVI_mciConfigure(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
|
|
|
|
{
|
|
|
|
WINE_MCIAVI *wma;
|
|
|
|
|
|
|
|
FIXME("(%04x, %08x, %p) : stub\n", wDevID, dwFlags, lpParms);
|
|
|
|
|
|
|
|
if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
|
|
|
|
|
|
|
|
wma = MCIAVI_mciGetOpenDev(wDevID);
|
|
|
|
if (wma == NULL) return MCIERR_INVALID_DEVICE_ID;
|
2010-03-10 16:21:22 +00:00
|
|
|
if (dwFlags & MCI_TEST) return 0;
|
2009-03-01 11:54:06 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*======================================================================*
|
|
|
|
* MCI AVI entry points *
|
|
|
|
*======================================================================*/
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* DriverProc (MCIAVI.@)
|
|
|
|
*/
|
|
|
|
LRESULT CALLBACK MCIAVI_DriverProc(DWORD_PTR dwDevID, HDRVR hDriv, UINT wMsg,
|
|
|
|
LPARAM dwParam1, LPARAM dwParam2)
|
|
|
|
{
|
|
|
|
TRACE("(%08lX, %p, %08X, %08lX, %08lX)\n",
|
|
|
|
dwDevID, hDriv, wMsg, dwParam1, dwParam2);
|
|
|
|
|
|
|
|
switch (wMsg) {
|
|
|
|
case DRV_LOAD: return 1;
|
|
|
|
case DRV_FREE: return 1;
|
|
|
|
case DRV_OPEN: return MCIAVI_drvOpen((LPCWSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSW)dwParam2);
|
|
|
|
case DRV_CLOSE: return MCIAVI_drvClose(dwDevID);
|
|
|
|
case DRV_ENABLE: return 1;
|
|
|
|
case DRV_DISABLE: return 1;
|
|
|
|
case DRV_QUERYCONFIGURE: return 1;
|
|
|
|
case DRV_CONFIGURE: return MCIAVI_drvConfigure(dwDevID);
|
|
|
|
case DRV_INSTALL: return DRVCNF_RESTART;
|
|
|
|
case DRV_REMOVE: return DRVCNF_RESTART;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* session instance */
|
|
|
|
if (dwDevID == 0xFFFFFFFF) return 1;
|
|
|
|
|
|
|
|
switch (wMsg) {
|
|
|
|
case MCI_OPEN_DRIVER: return MCIAVI_mciOpen (dwDevID, dwParam1, (LPMCI_DGV_OPEN_PARMSW) dwParam2);
|
|
|
|
case MCI_CLOSE_DRIVER: return MCIAVI_mciClose (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
|
|
|
|
case MCI_PLAY: return MCIAVI_mciPlay (dwDevID, dwParam1, (LPMCI_PLAY_PARMS) dwParam2);
|
|
|
|
case MCI_STOP: return MCIAVI_mciStop (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
|
|
|
|
case MCI_SET: return MCIAVI_mciSet (dwDevID, dwParam1, (LPMCI_DGV_SET_PARMS) dwParam2);
|
|
|
|
case MCI_PAUSE: return MCIAVI_mciPause (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
|
|
|
|
case MCI_RESUME: return MCIAVI_mciResume (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
|
|
|
|
case MCI_STATUS: return MCIAVI_mciStatus (dwDevID, dwParam1, (LPMCI_DGV_STATUS_PARMSW) dwParam2);
|
|
|
|
case MCI_GETDEVCAPS: return MCIAVI_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS) dwParam2);
|
|
|
|
case MCI_INFO: return MCIAVI_mciInfo (dwDevID, dwParam1, (LPMCI_DGV_INFO_PARMSW) dwParam2);
|
|
|
|
case MCI_SEEK: return MCIAVI_mciSeek (dwDevID, dwParam1, (LPMCI_SEEK_PARMS) dwParam2);
|
|
|
|
case MCI_PUT: return MCIAVI_mciPut (dwDevID, dwParam1, (LPMCI_DGV_PUT_PARMS) dwParam2);
|
|
|
|
case MCI_WINDOW: return MCIAVI_mciWindow (dwDevID, dwParam1, (LPMCI_DGV_WINDOW_PARMSW) dwParam2);
|
|
|
|
case MCI_LOAD: return MCIAVI_mciLoad (dwDevID, dwParam1, (LPMCI_DGV_LOAD_PARMSW) dwParam2);
|
|
|
|
case MCI_REALIZE: return MCIAVI_mciRealize (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
|
|
|
|
case MCI_UPDATE: return MCIAVI_mciUpdate (dwDevID, dwParam1, (LPMCI_DGV_UPDATE_PARMS) dwParam2);
|
|
|
|
case MCI_WHERE: return MCIAVI_mciWhere (dwDevID, dwParam1, (LPMCI_DGV_RECT_PARMS) dwParam2);
|
|
|
|
case MCI_STEP: return MCIAVI_mciStep (dwDevID, dwParam1, (LPMCI_DGV_STEP_PARMS) dwParam2);
|
|
|
|
case MCI_CUE: return MCIAVI_mciCue (dwDevID, dwParam1, (LPMCI_DGV_CUE_PARMS) dwParam2);
|
2017-06-03 22:28:56 +00:00
|
|
|
case MCI_BREAK: return MCIAVI_mciBreak (dwDevID, dwParam1, (LPMCI_BREAK_PARMS) dwParam2);
|
2009-03-01 11:54:06 +00:00
|
|
|
/* Digital Video specific */
|
|
|
|
case MCI_SETAUDIO: return MCIAVI_mciSetAudio (dwDevID, dwParam1, (LPMCI_DGV_SETAUDIO_PARMSW) dwParam2);
|
|
|
|
case MCI_SIGNAL: return MCIAVI_mciSignal (dwDevID, dwParam1, (LPMCI_DGV_SIGNAL_PARMS) dwParam2);
|
|
|
|
case MCI_SETVIDEO: return MCIAVI_mciSetVideo (dwDevID, dwParam1, (LPMCI_DGV_SETVIDEO_PARMSW) dwParam2);
|
|
|
|
case MCI_CONFIGURE: return MCIAVI_mciConfigure (dwDevID, dwParam1, (LPMCI_GENERIC_PARMS) dwParam2);
|
|
|
|
|
2010-03-10 16:21:22 +00:00
|
|
|
/* no editing, recording, saving, locking without inputs */
|
|
|
|
case MCI_CAPTURE:
|
|
|
|
case MCI_COPY:
|
|
|
|
case MCI_CUT:
|
|
|
|
case MCI_DELETE:
|
|
|
|
case MCI_FREEZE:
|
|
|
|
case MCI_LIST:
|
|
|
|
case MCI_MONITOR:
|
|
|
|
case MCI_PASTE:
|
|
|
|
case MCI_QUALITY:
|
|
|
|
case MCI_RECORD:
|
|
|
|
case MCI_RESERVE:
|
|
|
|
case MCI_RESTORE:
|
|
|
|
case MCI_SAVE:
|
|
|
|
case MCI_UNDO:
|
|
|
|
case MCI_UNFREEZE:
|
|
|
|
TRACE("Unsupported function [0x%x] flags=%08x\n", wMsg, (DWORD)dwParam1);
|
|
|
|
return MCIERR_UNSUPPORTED_FUNCTION;
|
2009-03-01 11:54:06 +00:00
|
|
|
case MCI_SPIN:
|
|
|
|
case MCI_ESCAPE:
|
2010-03-10 16:21:22 +00:00
|
|
|
WARN("Unsupported command [0x%x] %08x\n", wMsg, (DWORD)dwParam1);
|
2009-03-01 11:54:06 +00:00
|
|
|
break;
|
|
|
|
case MCI_OPEN:
|
|
|
|
case MCI_CLOSE:
|
|
|
|
FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
TRACE("Sending msg [%u] to default driver proc\n", wMsg);
|
|
|
|
return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
|
|
|
|
}
|
|
|
|
return MCIERR_UNRECOGNIZED_COMMAND;
|
|
|
|
}
|