windows-nt/Source/XPSP1/NT/multimedia/media/avi/mciavi.16/graphic.c

3012 lines
84 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/******************************************************************************
Copyright (C) Microsoft Corporation 1985-1991. All rights reserved.
Title: graphic.c - Multimedia Systems Media Control Interface
driver for AVI.
*****************************************************************************/
#include "graphic.h"
//#include "dispdib.h"
#include "cnfgdlg.h"
#include <string.h>
#ifdef EXPIRE
#include <dos.h>
#endif
#include "avitask.h"
#ifdef DEBUG
#define static
#endif
//
// This is the version number of MSVIDEO.DLL we need in order to run
// build 81 is when we added the VideoForWindowsVersion() function to
// MSVIDEO.DLL
//
// in build 85
// we removed the ICDecompressOpen() function and it became a macro.
// we added a parameter to ICGetDisplayFormat()
// we make DrawDibProfileDisplay() take a parameter
//
// in build 108
// Added ICOpenFunction() to open a hic using a function directly,
// without calling ICInstall
// Added some more ICDRAW_ messages
//
// in build 109
// Addded ICMessage() to compman
// removed ICDrawSuggest() made it a macro.
// Added ICMODE_FASTDECOMPRESS to ICLocate()
//
// Under NT the first build is sufficient !!! Is this true now?
//
#ifdef WIN32
#define MSVIDEO_VERSION (0x01000000) // 1.00.00.00
#else
#define MSVIDEO_VERSION (0x010a0000l+109) // 1.10.00.109
#endif
/* statics */
static INT swCommandTable = -1;
#ifdef WIN32
static SZCODE szDisplayDibLib[] = TEXT("DISPDB32.DLL");
#else
static SZCODE szDisplayDibLib[] = TEXT("DISPDIB.DLL");
#endif
/*
* files should be UNICODE. function names should not
*/
static SZCODEA szDisplayDib[] = "DisplayDib";
static SZCODEA szDisplayDibEx[] = "DisplayDibEx";
#ifdef WIN32
STATICDT SZCODE szMSVideo[] = TEXT("MSVFW32"); // With GetModuleHandle
#else
static SZCODE szMSVideo[] = TEXT("MSVIDEO");
#endif
BOOL gfEvil; // TRUE if we cant close cuz dialog box is up
BOOL gfEvilSysMenu; // TRUE if we cant close cuz system menu is up
NPMCIGRAPHIC npMCIList; // list of all open instances.
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api void | GraphicInit | This function is called when the DriverProc
* gets a DRV_LOAD message.
*
***************************************************************************/
BOOL FAR PASCAL GraphicInit(void)
{
InitializeDebugOutput("MCIAVI");
if (!GraphicWindowInit())
return FALSE;
swCommandTable = mciLoadCommandResource(ghModule, TEXT("mciavi"), 0);
return TRUE;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicDrvOpen | This function is called when the DriverProc
* gets a DRV_OPEN message. This happens each time that a new movie
* is opened thru MCI.
*
* @parm LPMCI_OPEN_DRIVER_PARMS | lpOpen | Far pointer to the standard
* MCI open parameters
*
* @rdesc Returns the mci device id. The installable driver interface will
* pass this ID to the DriverProc in the dwDriverID parameter on all
* subsequent messages. To fail the open, return 0L.
*
***************************************************************************/
DWORD PASCAL GraphicDrvOpen(LPMCI_OPEN_DRIVER_PARMS lpOpen)
{
/* Specify the custom command table and the device type */
lpOpen->wCustomCommandTable = swCommandTable;
lpOpen->wType = MCI_DEVTYPE_DIGITAL_VIDEO;
/* Set the device ID to the MCI Device ID */
return (DWORD) (UINT)lpOpen->wDeviceID;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api void | GraphicFree | This function is called when the DriverProc
* gets a DRV_FREE message. This happens when the drivers open count
* reaches 0.
*
***************************************************************************/
void PASCAL GraphicFree(void)
{
if (swCommandTable != -1) {
mciFreeCommandResource(swCommandTable);
swCommandTable = -1;
}
#ifdef WIN32
/*
* unregister class so we can re-register it next time we are loaded
*/
GraphicWindowFree();
#endif
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicDelayedNotify | This is a utility function that
* sends a notification saved with GraphicSaveCallback to mmsystem
* which posts a message to the application.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data.
*
* @parm UINT | wStatus | The type of notification to use can be one of
* MCI_NOTIFY_SUCCESSFUL, MCI_NOTIFY_SUPERSEDED, MCI_NOTIFY_ABORTED
* or MCI_NOTIFY_FAILURE (see MCI ispec.)
*
***************************************************************************/
void FAR PASCAL GraphicDelayedNotify(NPMCIGRAPHIC npMCI, UINT wStatus)
{
/* Send any saved notification */
if (npMCI->hCallback) {
// If the system menu is the only thing keeping us from closing, bring
// it down and then close.
if (gfEvilSysMenu)
SendMessage(npMCI->hwnd, WM_CANCELMODE, 0, 0);
// If a dialog box is up, and keeping us from closing, we can't send the
// notify or it will close us.
if (!gfEvil)
mciDriverNotify(npMCI->hCallback, npMCI->wDevID, wStatus);
npMCI->hCallback = NULL;
}
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicImmediateNotify | This is a utility function that
* sends a successful notification message to mmsystem if the
* notification flag is set and the error field is 0.
*
* @parm UINT | wDevID | device ID.
*
* @parm LPMCI_GENERIC_PARMS | lpParms | Far pointer to an MCI parameter
* block. The first field of every MCI parameter block is the
* callback handle.
*
* @parm DWORD | dwFlags | Parm. block flags - used to check whether the
* callback handle is valid.
*
* @parm DWORD | dwErr | Notification only occurs if the command is not
* returning an error.
*
***************************************************************************/
void FAR PASCAL GraphicImmediateNotify(UINT wDevID,
LPMCI_GENERIC_PARMS lpParms,
DWORD dwFlags, DWORD dwErr)
{
if (!LOWORD(dwErr) && (dwFlags & MCI_NOTIFY)) {
//Don't have an npMCI - see GraphicDelayedNotify
//if (gfEvil)
//SendMessage(npMCI->hwnd, WM_CANCELMODE, 0, 0);
// If a dialog box is up, and keeping us from closing, we can't send the
// notify or it will close us.
if (!gfEvil) // !!! EVIL !!!
mciDriverNotify((HANDLE) (UINT)lpParms->dwCallback,
wDevID, MCI_NOTIFY_SUCCESSFUL);
}
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicSaveCallback | This is a utility function that saves
* a new callback in the instance data block.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data.
*
* @parm HANDLE | hCallback | callback handle
*
***************************************************************************/
void NEAR PASCAL GraphicSaveCallback (NPMCIGRAPHIC npMCI, HANDLE hCallback)
{
/* If there's an old callback, kill it. */
GraphicDelayedNotify(npMCI, MCI_NOTIFY_SUPERSEDED);
/* Save new notification callback window handle */
npMCI->hCallback = hCallback;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicClose | This function closes the movie and
* releases the instance data.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD PASCAL GraphicClose (NPMCIGRAPHIC npMCI)
{
DWORD dwRet = 0L;
NPMCIGRAPHIC p;
if (npMCI) {
dwRet = DeviceClose (npMCI);
Assert(dwRet == 0);
// If the system menu is the only thing keeping us from closing, bring
// it down and then close.
if (gfEvilSysMenu)
SendMessage(npMCI->hwnd, WM_CANCELMODE, 0, 0);
if (gfEvil) {
DPF(("************************************************\n"));
DPF(("** EVIL: Failing the close because we'd die **\n"));
DPF(("************************************************\n"));
LeaveCrit(npMCI);
return MCIERR_DRIVER_INTERNAL;
}
/* If the default window still exists, close and destroy it. */
if (IsWindow(npMCI->hwndDefault)) {
if (!DestroyWindow(npMCI->hwndDefault))
dwRet = MCIERR_DRIVER_INTERNAL;
}
if (npMCI->szFilename) {
LocalFree((HANDLE) (npMCI->szFilename));
}
//
// find this instance on the list
//
if (npMCI == npMCIList) {
npMCIList = npMCI->npMCINext;
}
else {
for (p=npMCIList; p && p->npMCINext != npMCI; p=p->npMCINext)
;
Assert(p && p->npMCINext == npMCI);
p->npMCINext = npMCI->npMCINext;
}
#ifdef WIN32
// Delete the critical section object
LeaveCriticalSection(&npMCI->CritSec);
DeleteCriticalSection(&npMCI->CritSec);
#endif
/* Free the instance data block allocated in GraphicOpen */
LocalFree((HANDLE)npMCI);
}
return dwRet;
}
DWORD NEAR PASCAL FixFileName(NPMCIGRAPHIC npMCI, LPCTSTR lpName)
{
TCHAR ach[256];
ach[(sizeof(ach)/sizeof(TCHAR)) - 1] = TEXT('\0');
#ifndef WIN32
_fstrncpy(ach, (LPTSTR) lpName, (sizeof(ach)/sizeof(TCHAR)) - (1*sizeof(TCHAR)));
#else
wcsncpy(ach, (LPTSTR) lpName, (sizeof(ach)/sizeof(TCHAR)) - (1*sizeof(TCHAR)));
#endif
//
// treat any string that starts with a '@' as valid and pass it to the
// device any way.
//
if (ach[0] != '@')
{
if (!mmioOpen(ach, NULL, MMIO_PARSE))
return MCIERR_FILENAME_REQUIRED;
}
npMCI->szFilename = (NPTSTR) LocalAlloc(LPTR,
sizeof(TCHAR) * (lstrlen(ach) + 1));
if (!npMCI->szFilename) {
return MCIERR_OUT_OF_MEMORY;
}
lstrcpy(npMCI->szFilename, ach);
return 0L;
}
/**************************************************************************
***************************************************************************/
#define SLASH(c) ((c) == TEXT('/') || (c) == TEXT('\\'))
//#define SLASH(c) ((c) == '/' || (c) == '\\') // Filename Ascii??
STATICFN LPCTSTR FAR FileName(LPCTSTR szPath)
{
LPCTSTR sz;
sz = &szPath[lstrlen(szPath)];
for (; sz>szPath && !SLASH(*sz) && *sz!=TEXT(':');)
sz = CharPrev(szPath, sz);
return (sz>szPath ? sz + 1 : sz);
}
/****************************************************************************
****************************************************************************/
STATICFN DWORD NEAR PASCAL GetMSVideoVersion()
{
HANDLE h;
extern DWORD FAR PASCAL VideoForWindowsVersion(void);
//
// don't call VideoForWindowsVersion() if it does not exist or KERNEL
// will kill us with a undef dynalink error.
//
if ((h = GetModuleHandle(szMSVideo)) && GetProcAddress(h, (LPSTR) MAKEINTATOM(2)))
return VideoForWindowsVersion();
else
return 0;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicOpen | This function opens a movie file,
* initializes an instance data block, and creates the default
* stage window.
*
* @parm NPMCIGRAPHIC FAR * | lpnpMCI | Far pointer to a near pointer
* to instance data block to be filled in by this function.
*
* @parm DWORD | dwFlags | Flags for the open message.
*
* @parm LPMCI_DGV_OPEN_PARMS | Parameters for the open message.
*
* @parm UINT | wDeviceID | The MCI Device ID for this instance.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD PASCAL GraphicOpen (NPMCIGRAPHIC FAR * lpnpMCI, DWORD dwFlags,
LPMCI_DGV_OPEN_PARMS lpOpen, UINT wDeviceID)
{
NPMCIGRAPHIC npMCI;
DWORD dwStyle;
HWND hWnd;
HWND hWndParent;
DWORD dwRet;
if (dwFlags & MCI_OPEN_SHAREABLE) {
if (lpOpen->lpstrElementName == NULL ||
lpOpen->lpstrElementName[0] != '@') {
return MCIERR_UNSUPPORTED_FUNCTION;
}
}
//
// check the verion of MSVIDEO.DLL before going any further
// if we run a "new" version of MCIAVI on a old MSVIDEO.DLL
// then bad things will happen. We assume all MSVIDEO.DLLs
// will be backward compatible so we check for any version
// greater than the expected version.
//
DPF(("Video For Windows Version %d.%02d.%02d.%02d\n", HIBYTE(HIWORD(GetMSVideoVersion())), LOBYTE(HIWORD(GetMSVideoVersion())), HIBYTE(LOWORD(GetMSVideoVersion())), LOBYTE(LOWORD(GetMSVideoVersion())) ));
if (GetMSVideoVersion() < MSVIDEO_VERSION)
{
TCHAR achError[128];
TCHAR ach[40];
LoadString(ghModule, MCIAVI_BADMSVIDEOVERSION, achError, sizeof(achError)/sizeof(TCHAR));
LoadString(ghModule, MCIAVI_PRODUCTNAME, ach, sizeof(ach)/sizeof(TCHAR));
MessageBox(NULL,achError,ach,
#ifdef BIDI
MB_RTL_READING |
#endif
MB_OK|MB_SYSTEMMODAL|MB_ICONEXCLAMATION);
return MCIERR_DRIVER_INTERNAL;
}
#ifndef WIN32
#pragma message("Support passing in MMIOHANDLEs with OPEN_ELEMENT_ID?")
#endif
if (lpOpen->lpstrElementName == NULL) {
// they're doing an "open new".
// !!! handle this, probably by not actually reading a file.
// ack.
}
/* Be sure we have a real, non-empty filename, not an id. */
if ((!(dwFlags & MCI_OPEN_ELEMENT))
|| (lpOpen->lpstrElementName == NULL)
|| (*(lpOpen->lpstrElementName) == '\0'))
return MCIERR_UNSUPPORTED_FUNCTION;
// Allocate an instance data block. Code ASSUMES Zero Init.
if (!(npMCI = (NPMCIGRAPHIC) LocalAlloc(LPTR, sizeof (MCIGRAPHIC))))
return MCIERR_OUT_OF_MEMORY;
#ifdef WIN32
// init the per-device critsec
InitializeCriticalSection(&npMCI->CritSec);
npMCI->lCritRefCount = 0;
#endif
// now hold the critical section for the rest of the open
EnterCrit(npMCI);
#ifdef DEBUG
npMCI->mciid = MCIID;
#endif
//
// add this device to our list
//
npMCI->npMCINext = npMCIList;
npMCIList = npMCI;
npMCI->wMessageCurrent = MCI_OPEN;
// Allocate some space for the filename
// Copy the filename into the data block
dwRet = FixFileName(npMCI, lpOpen->lpstrElementName);
if (dwRet != 0L) {
// note we hold the critical section into GraphicClose, and
// release it just before deleting it within GraphicClose. This is
// because we need to hold it during the call to DeviceClose.
GraphicClose(npMCI);
return dwRet;
}
// Create the default window - the caller may
// supply style and parent window.
if (dwFlags & MCI_DGV_OPEN_PARENT)
hWndParent = lpOpen->hWndParent;
else
hWndParent = NULL;
if (dwFlags & MCI_DGV_OPEN_WS) {
// CW_USEDEFAULT can't be used with popups or children so
// if the user provides the style, default to full-screen.
dwStyle = lpOpen->dwStyle;
hWnd =
// Note: The CreateWindow/Ex call is written this way as on Win32
// CreateWindow is a MACRO, and hence the call must be contained
// within the preprocessor block.
#ifdef BIDI
CreateWindowEx(WS_EX_BIDI_SCROLL | WS_EX_BIDI_MENU |WS_EX_BIDI_NOICON,
szClassName,
FileName(npMCI->szFilename),
dwStyle,
0, 0,
GetSystemMetrics (SM_CXSCREEN),
GetSystemMetrics (SM_CYSCREEN),
hWndParent,
NULL, ghModule, (LPTSTR)npMCI);
#else
CreateWindow(
szClassName,
FileName(npMCI->szFilename),
dwStyle,
0, 0,
GetSystemMetrics (SM_CXSCREEN),
GetSystemMetrics (SM_CYSCREEN),
hWndParent,
NULL, ghModule, (LPTSTR)npMCI);
#endif
} else {
dwStyle = WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX |
WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
if (GetProfileInt("mciavi", "CreateVisible", 0)) {
DPF0(("Creating the window visible\n"));
dwStyle |= WS_VISIBLE;
} else {
DPF0(("Creating the window INvisible\n"));
}
hWnd =
#ifdef BIDI
CreateWindowEx(WS_EX_BIDI_SCROLL | WS_EX_BIDI_MENU |WS_EX_BIDI_NOICON,
szClassName,
FileName(npMCI->szFilename),
dwStyle,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
hWndParent,
NULL, ghModule, (LPTSTR)npMCI);
#else
CreateWindow(
szClassName,
FileName(npMCI->szFilename),
dwStyle,
CW_USEDEFAULT, 0,
CW_USEDEFAULT, 0,
hWndParent,
NULL, ghModule, (LPTSTR)npMCI);
#endif
}
if (!hWnd) {
// see above - we release and delete the critsec within GraphicClose
DPF0(("Failed to create the window\n"));
GraphicClose(npMCI);
return MCIERR_CREATEWINDOW;
}
/* Fill in some more of the instance data.
** The rest of the fields are filled in in DeviceOpen.
*/
npMCI->hCallingTask = GetCurrentTask();
npMCI->hCallback = NULL;
npMCI->wDevID = wDeviceID;
npMCI->hwndDefault = hWnd;
npMCI->hwnd = hWnd;
npMCI->dwTimeFormat = MCI_FORMAT_FRAMES;
npMCI->dwSpeedFactor = 1000;
npMCI->dwVolume = MAKELONG(500, 500);
npMCI->lTo = 0L;
npMCI->dwFlags = MCIAVI_PLAYAUDIO | MCIAVI_SHOWVIDEO;
npMCI->dwOptionFlags = ReadConfigInfo() | MCIAVIO_STRETCHTOWINDOW;
// perform device-specific initialization
dwRet = DeviceOpen(npMCI, dwFlags);
if (dwRet != 0) {
// see above - we release and delete the critsec within GraphicClose
GraphicClose(npMCI);
return dwRet;
}
*lpnpMCI = npMCI;
npMCI->wMessageCurrent = 0;
LeaveCrit(npMCI);
return 0L;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicLoad | This function supports the MCI_LOAD command.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the Load message.
*
* @parm LPMCI_DGV_LOAD_PARMS | lpLoad | Parameters for the LOAD message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicLoad(NPMCIGRAPHIC npMCI,
DWORD dwFlags, LPMCI_DGV_LOAD_PARMS lpLoad)
{
#ifndef LOADACTUALLYWORKS
return MCIERR_UNSUPPORTED_FUNCTION;
#else
DWORD dw;
if (!(dwFlags & MCI_LOAD_FILE))
return MCIERR_MISSING_PARAMETER;
dw = FixFileName(npMCI, lpLoad->lpfilename);
if (dw)
return dw;
dw = DeviceLoad(npMCI);
return dw;
#endif
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicSeek | This function sets the current frame. The
* device state after a seek is MCI_MODE_PAUSE
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the seek message.
*
* @parm LPMCI_DGV_SEEK_PARMS | lpSeek | Parameters for the seek message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicSeek (NPMCIGRAPHIC npMCI, DWORD dwFlags,
LPMCI_SEEK_PARMS lpSeek)
{
LONG lTo;
BOOL fTest = FALSE;
/* Do some range checking then pass onto the device-specific routine. */
if (dwFlags & MCI_TEST) {
dwFlags &= ~(MCI_TEST);
fTest = TRUE;
}
switch (dwFlags & (~(MCI_WAIT | MCI_NOTIFY))) {
case MCI_TO:
lTo = ConvertToFrames(npMCI, lpSeek->dwTo);
break;
case MCI_SEEK_TO_START:
lTo = 0;
break;
case MCI_SEEK_TO_END:
lTo = npMCI->lFrames;
break;
case 0:
return MCIERR_MISSING_PARAMETER;
default:
if (dwFlags & ~(MCI_TO |
MCI_SEEK_TO_START |
MCI_SEEK_TO_END |
MCI_WAIT |
MCI_NOTIFY))
return MCIERR_UNRECOGNIZED_KEYWORD;
else
return MCIERR_FLAGS_NOT_COMPATIBLE;
break;
}
if (!IsWindow(npMCI->hwnd))
return MCIERR_NO_WINDOW;
if (lTo < 0 || lTo > npMCI->lFrames)
return MCIERR_OUTOFRANGE;
if (fTest)
return 0L;
GraphicDelayedNotify (npMCI, MCI_NOTIFY_ABORTED);
if (dwFlags & MCI_NOTIFY) {
GraphicSaveCallback(npMCI, (HANDLE) (UINT)lpSeek->dwCallback);
}
/* Clear the 'repeat' flags */
npMCI->dwFlags &= ~(MCIAVI_REPEATING);
return DeviceSeek(npMCI, lTo, dwFlags);
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicCue | This function gets the movie ready to play,
* but leaves it paused.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the cue message.
*
* @parm LPMCI_DGV_CUE_PARMS | lpCue | Parameters for the cue message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicCue(NPMCIGRAPHIC npMCI, DWORD dwFlags,
LPMCI_DGV_CUE_PARMS lpCue)
{
LONG lTo;
DWORD dwRet = 0L;
if (dwFlags & MCI_DGV_CUE_INPUT)
return MCIERR_UNSUPPORTED_FUNCTION;
if (dwFlags & MCI_DGV_CUE_NOSHOW)
return MCIERR_UNSUPPORTED_FUNCTION;
if (dwFlags & MCI_TO) {
lTo = ConvertToFrames(npMCI, lpCue->dwTo);
if (lTo < 0L || lTo > npMCI->lFrames)
return MCIERR_OUTOFRANGE;
}
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
GraphicDelayedNotify(npMCI, MCI_NOTIFY_ABORTED);
if (dwFlags & MCI_NOTIFY) {
GraphicSaveCallback(npMCI, (HANDLE) (UINT)lpCue->dwCallback);
}
/* Clear the 'repeat' flags */
npMCI->dwFlags &= ~(MCIAVI_REPEATING);
/* Set up to play to end of file */
npMCI->lTo = npMCI->lFrames;
dwRet = DeviceCue(npMCI, lTo, dwFlags);
return dwRet;
}
#ifndef WIN32
#ifdef EXPIRE
//
// return the current date....
//
// dx = year
// ah = month
// al = day
//
#pragma optimize("", off)
DWORD DosGetDate(void)
{
if (0)
return 0;
_asm {
mov ah,2ah
int 21h
mov ax,dx
mov dx,cx
}
}
#pragma optimize("", on)
#endif
#endif
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicPlay | This function starts playback of the movie. If
* the reverse flag is specified, the movie plays backwards. If the fast
* or slow flags are specified the movie plays faster or slower.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the play message.
*
* @parm LPMCI_DGV_PLAY_PARMS | lpPlay | Parameters for the play message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicPlay (NPMCIGRAPHIC npMCI, DWORD dwFlags,
LPMCI_PLAY_PARMS lpPlay )
{
LONG lTo, lFrom;
DWORD dwRet;
#ifdef EXPIRE
#pragma message("Remove the expiration code after Beta ships")
if (DosGetDate() >= EXPIRE)
{
return MCIERR_AVI_EXPIRED;
}
#endif
if (!(dwFlags & (MCI_MCIAVI_PLAY_FULLSCREEN | MCI_MCIAVI_PLAY_WINDOW)) &&
(npMCI->dwOptionFlags & MCIAVIO_USEVGABYDEFAULT)) {
if (npMCI->dwOptionFlags & MCIAVIO_ZOOMBY2)
dwFlags |= MCI_MCIAVI_PLAY_FULLBY2;
else
dwFlags |= MCI_MCIAVI_PLAY_FULLSCREEN;
}
if (dwFlags & (MCI_MCIAVI_PLAY_FULLSCREEN | MCI_MCIAVI_PLAY_FULLBY2)) {
#if 0
if (ghDISPDIB == NULL) {
UINT w;
w = SetErrorMode(SEM_NOOPENFILEERRORBOX);
#ifndef WIN32
if ((ghDISPDIB = LoadLibrary(szDisplayDibLib)) > HINSTANCE_ERROR)
#else
if ((ghDISPDIB = LoadLibrary(szDisplayDibLib)) != NULL)
#endif
{
(FARPROC)DisplayDibProc = GetProcAddress(ghDISPDIB, szDisplayDib);
(FARPROC)DisplayDibExProc = GetProcAddress(ghDISPDIB, szDisplayDibEx);
}
else
ghDISPDIB = (HINSTANCE)-1;
SetErrorMode(w);
DPF(("ghDISPDIB=0x%04x, DisplayDibProc=0x%08lx\n", ghDISPDIB, DisplayDibProc));
}
if (DisplayDibProc == NULL)
return MCIERR_AVI_NODISPDIB;
#endif
} else {
if (!IsWindow(npMCI->hwnd))
return MCIERR_NO_WINDOW;
npMCI->dwFlags |= MCIAVI_NEEDTOSHOW;
}
/* Range checks : 0 < 'from' <= 'to' <= last frame */
if (dwFlags & MCI_TO) {
lTo = ConvertToFrames(npMCI, lpPlay->dwTo);
if (lTo < 0L || lTo > npMCI->lFrames)
return MCIERR_OUTOFRANGE;
} else if (dwFlags & MCI_DGV_PLAY_REVERSE)
lTo = 0;
else
lTo = npMCI->lFrames;
dwFlags |= MCI_TO;
if (dwFlags & MCI_FROM) {
lFrom = ConvertToFrames(npMCI, lpPlay->dwFrom);
if (lFrom < 0L || lFrom > npMCI->lFrames)
return MCIERR_OUTOFRANGE;
} else if (dwRet = DevicePosition(npMCI, &lFrom))
return dwRet;
/* check 'to' and 'from' relationship. */
if (lTo < lFrom)
dwFlags |= MCI_DGV_PLAY_REVERSE;
if ((lFrom < lTo) && (dwFlags & MCI_DGV_PLAY_REVERSE))
return MCIERR_OUTOFRANGE;
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
/* We want any previous playing to be aborted if and only if a 'from'
** parameter is specified. If only a new 'to' parameter is specified,
** we can just change the 'to' value, and play will stop at the
** proper time.
*/
/* set the 'to' position after we've stopped, if we're stopping. */
if (dwFlags & MCI_FROM) {
/* If MCI_FROM flag is specified then reset the starting location */
DeviceStop(npMCI, MCI_WAIT);
npMCI->lFrom = lFrom;
} else {
/* We still set the "From" variable, so that we'll correctly
** play from the current position.
** !!! Should this be done instead by updating lFrom to be the
** current position when playback ends?
*/
npMCI->lFrom = lFrom;
}
/* If we're changing the "to" position, abort any pending notify. */
if (lTo != npMCI->lTo) {
GraphicDelayedNotify (npMCI, MCI_NOTIFY_ABORTED);
}
/* Don't set up notify until here, so that the seek won't make it happen*/
if (dwFlags & MCI_NOTIFY) {
GraphicSaveCallback(npMCI, (HANDLE) (UINT)lpPlay->dwCallback);
}
/* Set up the 'repeat' flags */
npMCI->dwFlags &= ~(MCIAVI_REPEATING);
if (dwFlags & MCI_DGV_PLAY_REPEAT) {
/* If from position isn't given, repeat from either the beginning or
** end of file as appropriate.
*/
npMCI->lRepeatFrom =
(dwFlags & MCI_FROM) ? lFrom :
((dwFlags & MCI_DGV_PLAY_REVERSE) ? npMCI->lFrames : 0);
}
/* Go ahead and actually play... */
return DevicePlay(npMCI, lTo, dwFlags);
}
/***************************************************************************
*
* @doc INTERNAL MCIWAVE
*
* @api DWORD | GraphicStep | This function steps through several frames
* of a movie. If the reverse flag is set, then the step is backwards.
* If the step count is not specified then it defaults to 1. If the
* step count plus the current position exceeds the movie length, the
* step is out of range.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the step message.
*
* @parm LPMCI_DGV_STEP_PARMS | lpStep | Parameters for the step message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicStep (NPMCIGRAPHIC npMCI, DWORD dwFlags,
LPMCI_DGV_STEP_PARMS lpStep)
{
LONG lFrameCur;
LONG lFrames;
DWORD dwRet;
BOOL fReverse;
BOOL fSeekExactOff;
fReverse = (dwFlags & MCI_DGV_STEP_REVERSE) == MCI_DGV_STEP_REVERSE;
// Default to 1 frame step if frame count is not specified
if (dwFlags & MCI_DGV_STEP_FRAMES) {
lFrames = (LONG) lpStep->dwFrames;
if (fReverse) {
if (lFrames < 0)
return MCIERR_FLAGS_NOT_COMPATIBLE;
}
} else
lFrames = 1;
lFrames = fReverse ? -lFrames : lFrames;
/* stop before figuring out whether frame count is within range, */
/* unless the TEST flag is set. */
if (!(dwFlags & MCI_TEST)) {
if (dwRet = DeviceStop(npMCI, MCI_WAIT))
return dwRet;
}
if (dwRet = DevicePosition(npMCI, &lFrameCur))
return dwRet;
if ((lFrames + lFrameCur > npMCI->lFrames) ||
(lFrames + lFrameCur < 0))
return MCIERR_OUTOFRANGE;
if (!IsWindow(npMCI->hwnd))
return MCIERR_NO_WINDOW;
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
GraphicDelayedNotify (npMCI, MCI_NOTIFY_ABORTED);
/* Clear the 'repeat' flags */
npMCI->dwFlags &= ~(MCIAVI_REPEATING);
if (dwFlags & MCI_NOTIFY) {
GraphicSaveCallback(npMCI, (HANDLE) (UINT)lpStep->dwCallback);
}
fSeekExactOff = (npMCI->dwOptionFlags & MCIAVIO_SEEKEXACT) == 0;
npMCI->dwOptionFlags |= MCIAVIO_SEEKEXACT;
npMCI->dwFlags |= MCIAVI_NEEDTOSHOW;
if (fSeekExactOff) {
/* If we were not in seek exact mode, make seek finish
** before we turn seek exact back off.
*/
dwRet = DeviceSeek(npMCI, lFrames + lFrameCur, dwFlags | MCI_WAIT);
npMCI->dwOptionFlags &= ~(MCIAVIO_SEEKEXACT);
} else
dwRet = DeviceSeek(npMCI, lFrames + lFrameCur, dwFlags);
return dwRet;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicStop | This function stops playback of the movie.
* After a stop the state will be MCI_MODE_STOP. The frame counter
* is not reset.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the stop message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicStop (NPMCIGRAPHIC npMCI, DWORD dwFlags,
LPMCI_GENERIC_PARMS lpParms)
{
if (!IsWindow(npMCI->hwnd))
return MCIERR_NO_WINDOW;
if (dwFlags & MCI_DGV_STOP_HOLD)
return MCIERR_UNSUPPORTED_FUNCTION;
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
GraphicDelayedNotify (npMCI, MCI_NOTIFY_ABORTED);
/* Do we need to handle notify here? */
return DeviceStop(npMCI, dwFlags);
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicPause | Pauses movie playback.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicPause(NPMCIGRAPHIC npMCI, DWORD dwFlags,
LPMCI_GENERIC_PARMS lpParms)
{
if (!IsWindow(npMCI->hwnd))
return MCIERR_NO_WINDOW;
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
if (dwFlags & MCI_NOTIFY) {
GraphicSaveCallback(npMCI, (HANDLE) (UINT)lpParms->dwCallback);
}
return DevicePause(npMCI, dwFlags);
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicResume | This function resumes playback of a paused
* movie.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicResume (NPMCIGRAPHIC npMCI,
DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
{
DWORD dwRet;
UINT wMode;
// Resume is only allowed if MCIAVI is paused or playing
wMode = DeviceMode(npMCI);
if (wMode != MCI_MODE_PAUSE && wMode != MCI_MODE_PLAY)
return MCIERR_NONAPPLICABLE_FUNCTION;
if (!IsWindow(npMCI->hwnd))
return MCIERR_NO_WINDOW;
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
if (dwFlags & MCI_NOTIFY) {
GraphicSaveCallback(npMCI, (HANDLE) (UINT)lpParms->dwCallback);
}
dwRet = DeviceResume(npMCI, dwFlags & MCI_WAIT);
return dwRet;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicStatus | This function returns numeric status info.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the status message.
*
* @parm LPMCI_STATUS_PARMS | lpPlay | Parameters for the status message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicStatus (NPMCIGRAPHIC npMCI,
DWORD dwFlags, LPMCI_DGV_STATUS_PARMS lpStatus)
{
DWORD dwRet = 0L;
if (dwFlags & (MCI_DGV_STATUS_DISKSPACE))
return MCIERR_UNSUPPORTED_FUNCTION;
if (dwFlags & MCI_STATUS_ITEM) {
lpStatus->dwReturn = 0L;
if ((dwFlags & MCI_TRACK) &&
!((lpStatus->dwItem == MCI_STATUS_POSITION) ||
(lpStatus->dwItem == MCI_STATUS_LENGTH)))
return MCIERR_FLAGS_NOT_COMPATIBLE;
if ((dwFlags & MCI_STATUS_START) &&
(lpStatus->dwItem != MCI_STATUS_POSITION))
return MCIERR_FLAGS_NOT_COMPATIBLE;
if (dwFlags & MCI_DGV_STATUS_REFERENCE)
return MCIERR_FLAGS_NOT_COMPATIBLE;
switch (lpStatus->dwItem) {
case MCI_STATUS_POSITION:
if (dwFlags & MCI_TRACK) {
/* POSITION with TRACK means return the start of the */
/* track. */
if (lpStatus->dwTrack != 1)
dwRet = MCIERR_OUTOFRANGE;
else
/* return start frame of track (always 0) */
lpStatus->dwReturn = 0L;
} else if (dwFlags & MCI_STATUS_START)
// POSITION with START means return the starting playable
// position of the media.
lpStatus->dwReturn = 0L;
else {
/* Otherwise return current frame */
dwRet = DevicePosition(npMCI, (LPLONG) &lpStatus->dwReturn);
lpStatus->dwReturn = ConvertFromFrames(npMCI,
(LONG) lpStatus->dwReturn);
}
break;
case MCI_STATUS_LENGTH:
if (dwFlags & MCI_TRACK && lpStatus->dwTrack != 1) {
/* LENGTH with TRACK means return the length of track */
lpStatus->dwReturn = 0L;
dwRet = MCIERR_OUTOFRANGE;
}
lpStatus->dwReturn = ConvertFromFrames(npMCI, npMCI->lFrames);
break;
case MCI_STATUS_NUMBER_OF_TRACKS:
case MCI_STATUS_CURRENT_TRACK:
lpStatus->dwReturn = 1L;
break;
case MCI_STATUS_READY:
/* Return TRUE if device can receive commands */
if (DeviceMode(npMCI) != MCI_MODE_NOT_READY)
lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
else
lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_STATUS_MODE:
{
WORD wMode;
wMode = DeviceMode(npMCI);
lpStatus->dwReturn = MAKEMCIRESOURCE(wMode, wMode);
dwRet = MCI_RESOURCE_RETURNED;
}
break;
case MCI_DGV_STATUS_PAUSE_MODE:
if (DeviceMode(npMCI) != MCI_MODE_PAUSE)
dwRet = MCIERR_NONAPPLICABLE_FUNCTION;
else {
lpStatus->dwReturn = MAKEMCIRESOURCE(MCI_MODE_PLAY, MCI_MODE_PLAY);
dwRet = MCI_RESOURCE_RETURNED;
}
break;
case MCI_STATUS_MEDIA_PRESENT:
lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_DGV_STATUS_FORWARD:
if (npMCI->dwFlags & MCIAVI_REVERSE)
lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
else
lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_DGV_STATUS_HWND:
lpStatus->dwReturn = (DWORD)(UINT)npMCI->hwnd;
if (!IsWindow(npMCI->hwnd))
dwRet = MCIERR_NO_WINDOW;
break;
case MCI_DGV_STATUS_HPAL:
// lpStatus->dwReturn = (DWORD) (UINT) DrawDibGetPalette(npMCI->hdd);
lpStatus->dwReturn = 0;
if (npMCI->nVideoStreams == 0) {
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
} else {
dwRet = ICSendMessage(npMCI->hicDraw, ICM_DRAW_GET_PALETTE, 0, 0);
if (dwRet == ICERR_UNSUPPORTED) {
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
} else {
lpStatus->dwReturn = dwRet;
dwRet = 0;
}
}
DPF2(("Status HPAL returns: %lu\n", lpStatus->dwReturn));
break;
case MCI_STATUS_TIME_FORMAT:
lpStatus->dwReturn = MAKEMCIRESOURCE(npMCI->dwTimeFormat,
npMCI->dwTimeFormat + MCI_FORMAT_RETURN_BASE);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_DGV_STATUS_AUDIO:
lpStatus->dwReturn = (npMCI->dwFlags & MCIAVI_PLAYAUDIO) ?
(MAKEMCIRESOURCE(MCI_ON, MCI_ON_S)) :
(MAKEMCIRESOURCE(MCI_OFF, MCI_OFF_S));
dwRet = MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
break;
case MCI_DGV_STATUS_WINDOW_VISIBLE:
if (npMCI->hwnd && IsWindowVisible(npMCI->hwnd))
lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
else
lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_DGV_STATUS_WINDOW_MINIMIZED:
if (npMCI->hwnd && IsIconic(npMCI->hwnd))
lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
else
lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_DGV_STATUS_WINDOW_MAXIMIZED:
if (npMCI->hwnd && IsZoomed(npMCI->hwnd))
lpStatus->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
else
lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_DGV_STATUS_SAMPLESPERSEC:
case MCI_DGV_STATUS_AVGBYTESPERSEC:
case MCI_DGV_STATUS_BLOCKALIGN:
case MCI_DGV_STATUS_BITSPERSAMPLE:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
case MCI_DGV_STATUS_BITSPERPEL:
if (npMCI->psiVideo)
lpStatus->dwReturn = ((LPBITMAPINFOHEADER)npMCI->psiVideo->lpFormat)->biBitCount;
else
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
#ifndef WIN32
#pragma message("Are we going to support brightness/color/contrast/tint?")
#endif
case MCI_DGV_STATUS_BRIGHTNESS:
case MCI_DGV_STATUS_COLOR:
case MCI_DGV_STATUS_CONTRAST:
case MCI_DGV_STATUS_TINT:
case MCI_DGV_STATUS_GAMMA:
case MCI_DGV_STATUS_SHARPNESS:
case MCI_DGV_STATUS_FILE_MODE:
case MCI_DGV_STATUS_FILE_COMPLETION:
case MCI_DGV_STATUS_KEY_INDEX:
case MCI_DGV_STATUS_KEY_COLOR:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
case MCI_DGV_STATUS_FILEFORMAT:
// Fall through to Unsupported case...
// lpStatus->dwReturn = MAKEMCIRESOURCE(MCI_DGV_FF_AVI,
// MCI_DGV_FF_AVI);
// dwRet = MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
// break;
//
case MCI_DGV_STATUS_BASS:
case MCI_DGV_STATUS_TREBLE:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
case MCI_DGV_STATUS_VOLUME:
{
WORD wLeftVolume, wRightVolume;
// Be sure volume is up to date....
DeviceGetVolume(npMCI);
wLeftVolume = LOWORD(npMCI->dwVolume);
wRightVolume = LOWORD(npMCI->dwVolume);
switch (dwFlags & (MCI_DGV_STATUS_LEFT | MCI_DGV_STATUS_RIGHT)) {
case MCI_DGV_STATUS_LEFT:
lpStatus->dwReturn = (DWORD) wLeftVolume;
break;
case 0:
lpStatus->dwReturn = (DWORD) wRightVolume;
break;
default:
lpStatus->dwReturn = ((DWORD) wLeftVolume + (DWORD) wRightVolume) / 2;
break;
}
}
break;
case MCI_DGV_STATUS_MONITOR:
lpStatus->dwReturn = (DWORD)
MAKEMCIRESOURCE(MCI_DGV_MONITOR_FILE,
MCI_DGV_FILE_S);
dwRet = MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
break;
case MCI_DGV_STATUS_SEEK_EXACTLY:
lpStatus->dwReturn =
(npMCI->dwOptionFlags & MCIAVIO_SEEKEXACT) ?
(MAKEMCIRESOURCE(MCI_ON, MCI_ON_S)) :
(MAKEMCIRESOURCE(MCI_OFF, MCI_OFF_S));
dwRet = MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
break;
case MCI_DGV_STATUS_SIZE:
/* We haven't reserved any space, so return zero. */
lpStatus->dwReturn = 0L;
break;
case MCI_DGV_STATUS_SMPTE:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
case MCI_DGV_STATUS_UNSAVED:
lpStatus->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_DGV_STATUS_VIDEO:
lpStatus->dwReturn = (npMCI->dwFlags & MCIAVI_SHOWVIDEO) ?
(MAKEMCIRESOURCE(MCI_ON, MCI_ON_S)) :
(MAKEMCIRESOURCE(MCI_OFF, MCI_OFF_S));
dwRet = MCI_RESOURCE_RETURNED | MCI_RESOURCE_DRIVER;
break;
case MCI_DGV_STATUS_SPEED:
lpStatus->dwReturn = npMCI->dwSpeedFactor;
break;
case MCI_DGV_STATUS_FRAME_RATE:
{
DWORD dwTemp;
dwTemp = npMCI->dwMicroSecPerFrame;
/* If they haven't specifically asked for the "nominal"
** rate of play, adjust by the current speed.
*/
if (!(dwFlags & MCI_DGV_STATUS_NOMINAL))
dwTemp = muldiv32(dwTemp, 1000L, npMCI->dwSpeedFactor);
if (dwTemp == 0)
lpStatus->dwReturn = 1000;
else
/* Our return value is in "thousandths of frames/sec",
** and dwTemp is the number of microseconds per frame.
** Thus, we divide a billion microseconds by dwTemp.
*/
lpStatus->dwReturn = muldiv32(1000000L, 1000L, dwTemp);
break;
}
case MCI_DGV_STATUS_AUDIO_STREAM:
lpStatus->dwReturn = 0;
if (npMCI->nAudioStreams) {
int stream;
for (stream = 0; stream < npMCI->streams; stream++) {
if (SH(stream).fccType == streamtypeAUDIO)
++lpStatus->dwReturn;
if (stream == npMCI->nAudioStream)
break;
}
}
break;
case MCI_DGV_STATUS_VIDEO_STREAM:
case MCI_DGV_STATUS_AUDIO_INPUT:
case MCI_DGV_STATUS_AUDIO_RECORD:
case MCI_DGV_STATUS_AUDIO_SOURCE:
case MCI_DGV_STATUS_VIDEO_RECORD:
case MCI_DGV_STATUS_VIDEO_SOURCE:
case MCI_DGV_STATUS_VIDEO_SRC_NUM:
case MCI_DGV_STATUS_MONITOR_METHOD:
case MCI_DGV_STATUS_STILL_FILEFORMAT:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
case MCI_AVI_STATUS_FRAMES_SKIPPED:
lpStatus->dwReturn = npMCI->lSkippedFrames;
break;
case MCI_AVI_STATUS_AUDIO_BREAKS:
lpStatus->dwReturn = npMCI->lAudioBreaks;
break;
case MCI_AVI_STATUS_LAST_PLAY_SPEED:
lpStatus->dwReturn = npMCI->dwSpeedPercentage;
break;
default:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
} /* end switch (item) */
} else if (dwFlags & MCI_DGV_STATUS_REFERENCE) {
if (lpStatus->dwReference > (DWORD) npMCI->lFrames)
dwRet = MCIERR_OUTOFRANGE;
else if (npMCI->psiVideo) {
lpStatus->dwReference = MovieToStream(npMCI->psiVideo,
lpStatus->dwReference);
lpStatus->dwReturn = FindPrevKeyFrame(npMCI, npMCI->psiVideo,
lpStatus->dwReference);
lpStatus->dwReturn = StreamToMovie(npMCI->psiVideo,
lpStatus->dwReturn);
}
else {
lpStatus->dwReturn = 0;
}
} else /* item flag not set */
dwRet = MCIERR_MISSING_PARAMETER;
if ((dwFlags & MCI_TEST) && (LOWORD(dwRet) == 0)) {
/* There is no error, but the test flag is on. Return as little
** as possible.
*/
dwRet = 0;
lpStatus->dwReturn = 0;
}
return dwRet;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicInfo | This function returns alphanumeric information.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the info. message.
*
* @parm LPMCI_INFO_PARMS | lpPlay | Parameters for the info message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicInfo(NPMCIGRAPHIC npMCI, DWORD dwFlags,
LPMCI_DGV_INFO_PARMS lpInfo)
{
DWORD dwRet = 0L;
TCHAR ch = TEXT('\0');
BOOL fTest = FALSE;
if (!lpInfo->lpstrReturn)
return MCIERR_PARAM_OVERFLOW;
if (dwFlags & MCI_TEST)
fTest = TRUE;
dwFlags &= ~(MCI_WAIT | MCI_NOTIFY | MCI_TEST);
switch (dwFlags) {
case 0L:
return MCIERR_MISSING_PARAMETER;
case MCI_INFO_FILE:
if (!npMCI)
return MCIERR_UNSUPPORTED_FUNCTION;
if (lpInfo->dwRetSize < (DWORD)(lstrlen(npMCI->szFilename) + 1)) {
ch = npMCI->szFilename[lpInfo->dwRetSize];
npMCI->szFilename[lpInfo->dwRetSize] = '\0';
dwRet = MCIERR_PARAM_OVERFLOW;
}
lstrcpy (lpInfo->lpstrReturn, npMCI->szFilename);
if (ch)
npMCI->szFilename[lpInfo->dwRetSize] = ch;
break;
case MCI_INFO_PRODUCT:
#ifdef DEBUG
#include "..\verinfo\usa\verinfo.h"
wsprintf(lpInfo->lpstrReturn,
TEXT("VfW %d.%02d.%02d"), MMVERSION, MMREVISION, MMRELEASE);
#else
/* !!! Not returning PARAM_OVERFLOW here but I am above - lazy eh */
LoadString(ghModule, MCIAVI_PRODUCTNAME, lpInfo->lpstrReturn,
(UINT)lpInfo->dwRetSize);
#endif
break;
case MCI_DGV_INFO_TEXT:
if (!npMCI)
return MCIERR_UNSUPPORTED_FUNCTION;
if (IsWindow(npMCI->hwnd))
GetWindowText(npMCI->hwnd, lpInfo->lpstrReturn,
LOWORD(lpInfo->dwRetSize));
else
dwRet = MCIERR_NO_WINDOW;
break;
case MCI_INFO_VERSION:
/* !!! Not returning PARAM_OVERFLOW here but I am above - lazy eh */
LoadString(ghModule, MCIAVI_VERSION, lpInfo->lpstrReturn,
(UINT)lpInfo->dwRetSize);
break;
case MCI_DGV_INFO_USAGE:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
case MCI_DGV_INFO_ITEM:
switch (lpInfo->dwItem) {
case MCI_DGV_INFO_AUDIO_QUALITY:
case MCI_DGV_INFO_VIDEO_QUALITY:
case MCI_DGV_INFO_STILL_QUALITY:
case MCI_DGV_INFO_AUDIO_ALG:
case MCI_DGV_INFO_VIDEO_ALG:
case MCI_DGV_INFO_STILL_ALG:
default:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
}
break;
default:
dwRet = MCIERR_FLAGS_NOT_COMPATIBLE;
break;
}
if (fTest && (LOWORD(dwRet) == 0)) {
/* There is no error, but the test flag is on. Return as little
** as possible.
*/
dwRet = 0;
if (lpInfo->dwRetSize)
lpInfo->lpstrReturn[0] = '\0';
}
return dwRet;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicSet | This function sets various options.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the set message.
*
* @parm LPMCI_SET_PARMS | lpSet | Parameters for the set message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicSet (NPMCIGRAPHIC npMCI,
DWORD dwFlags, LPMCI_DGV_SET_PARMS lpSet)
{
DWORD dwRet = 0L;
DWORD dwAction;
if (dwFlags & MCI_DGV_SET_FILEFORMAT)
return MCIERR_UNSUPPORTED_FUNCTION;
if (dwFlags & MCI_DGV_SET_STILL)
return MCIERR_UNSUPPORTED_FUNCTION;
dwAction = dwFlags & (MCI_SET_TIME_FORMAT |
MCI_SET_VIDEO |
MCI_SET_AUDIO |
MCI_DGV_SET_SEEK_EXACTLY |
MCI_DGV_SET_SPEED
);
dwFlags &= (MCI_SET_ON |
MCI_SET_OFF |
MCI_TEST
);
/* First, check if the parameters are all okay */
if (!dwAction)
return MCIERR_UNSUPPORTED_FUNCTION;
if (dwAction & MCI_SET_TIME_FORMAT) {
if (lpSet->dwTimeFormat != MCI_FORMAT_FRAMES
&& lpSet->dwTimeFormat != MCI_FORMAT_MILLISECONDS)
return MCIERR_UNSUPPORTED_FUNCTION;
}
if ((dwAction & MCI_SET_AUDIO) &&
(lpSet->dwAudio != MCI_SET_AUDIO_ALL)) {
return MCIERR_UNSUPPORTED_FUNCTION;
}
if (dwAction & MCI_DGV_SET_SPEED) {
if (lpSet->dwSpeed > 100000L)
return MCIERR_OUTOFRANGE;
}
switch (dwFlags & (MCI_SET_ON | MCI_SET_OFF)) {
case 0:
if (dwAction & (MCI_SET_AUDIO |
MCI_SET_VIDEO |
MCI_DGV_SET_SEEK_EXACTLY))
return MCIERR_MISSING_PARAMETER;
break;
case MCI_SET_ON | MCI_SET_OFF:
return MCIERR_FLAGS_NOT_COMPATIBLE;
default:
if (dwAction & (MCI_DGV_SET_SPEED | MCI_SET_TIME_FORMAT))
return MCIERR_FLAGS_NOT_COMPATIBLE;
break;
}
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
/* Now, actually carry out the command */
if (dwAction & MCI_SET_TIME_FORMAT)
npMCI->dwTimeFormat = lpSet->dwTimeFormat;
if (dwAction & MCI_SET_VIDEO) {
npMCI->dwFlags &= ~(MCIAVI_SHOWVIDEO);
if (dwFlags & MCI_SET_ON) {
npMCI->dwFlags |= MCIAVI_SHOWVIDEO;
InvalidateRect(npMCI->hwnd, NULL, FALSE);
}
}
if (dwAction & MCI_DGV_SET_SEEK_EXACTLY) {
npMCI->dwOptionFlags &= ~(MCIAVIO_SEEKEXACT);
if (dwFlags & MCI_SET_ON)
npMCI->dwOptionFlags |= MCIAVIO_SEEKEXACT;
}
if (dwAction & MCI_DGV_SET_SPEED) {
dwRet = DeviceSetSpeed(npMCI, lpSet->dwSpeed);
}
if (dwRet == 0L && (dwAction & MCI_SET_AUDIO)) {
dwRet = DeviceMute(npMCI, dwFlags & MCI_SET_OFF ? TRUE : FALSE);
}
return dwRet;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicSetAudio | This function sets various audio options.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the set audio message.
*
* @parm LPMCI_SET_PARMS | lpSet | Parameters for the set audio message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicSetAudio (NPMCIGRAPHIC npMCI,
DWORD dwFlags, LPMCI_DGV_SETAUDIO_PARMS lpSet)
{
DWORD dwRet = 0L;
if (npMCI->nAudioStreams == 0) {
return MCIERR_UNSUPPORTED_FUNCTION;
}
if ((dwFlags & MCI_DGV_SETAUDIO_ITEM) &&
(lpSet->dwItem == MCI_DGV_SETAUDIO_VOLUME) &&
(dwFlags & MCI_DGV_SETAUDIO_VALUE)) {
WORD wLeft, wRight;
if (dwFlags & (MCI_DGV_SETAUDIO_ALG |
MCI_DGV_SETAUDIO_QUALITY |
MCI_DGV_SETAUDIO_RECORD |
MCI_DGV_SETAUDIO_CLOCKTIME))
return MCIERR_UNSUPPORTED_FUNCTION;
if (lpSet->dwValue > 1000L)
return MCIERR_OUTOFRANGE;
if (dwFlags & MCI_TEST)
return 0L;
// Be sure volume is up to date....
DeviceGetVolume(npMCI);
wLeft = LOWORD(npMCI->dwVolume);
wRight = HIWORD(npMCI->dwVolume);
if (!(dwFlags & MCI_DGV_SETAUDIO_RIGHT))
wLeft = (WORD) lpSet->dwValue;
if (!(dwFlags & MCI_DGV_SETAUDIO_LEFT))
wRight = (WORD) lpSet->dwValue;
dwRet = DeviceSetVolume(npMCI, MAKELONG(wLeft, wRight));
} else if ((dwFlags & MCI_DGV_SETAUDIO_ITEM) &&
(lpSet->dwItem == MCI_DGV_SETAUDIO_STREAM) &&
(dwFlags & MCI_DGV_SETAUDIO_VALUE)) {
if (dwFlags & (MCI_DGV_SETAUDIO_ALG |
MCI_DGV_SETAUDIO_QUALITY |
MCI_DGV_SETAUDIO_RECORD |
MCI_DGV_SETAUDIO_LEFT |
MCI_DGV_SETAUDIO_CLOCKTIME |
MCI_DGV_SETAUDIO_RIGHT))
return MCIERR_UNSUPPORTED_FUNCTION;
if (lpSet->dwValue > (DWORD) npMCI->nAudioStreams || lpSet->dwValue == 0)
return MCIERR_OUTOFRANGE;
if (dwFlags & MCI_TEST)
return 0L;
dwRet = DeviceSetAudioStream(npMCI, (WORD) lpSet->dwValue);
} else if (dwFlags & (MCI_DGV_SETAUDIO_ITEM |
MCI_DGV_SETAUDIO_VALUE |
MCI_DGV_SETAUDIO_ALG |
MCI_DGV_SETAUDIO_QUALITY |
MCI_DGV_SETAUDIO_RECORD |
MCI_DGV_SETAUDIO_LEFT |
MCI_DGV_SETAUDIO_CLOCKTIME |
MCI_DGV_SETAUDIO_RIGHT))
return MCIERR_UNSUPPORTED_FUNCTION;
switch (dwFlags & (MCI_SET_ON | MCI_SET_OFF)) {
case MCI_SET_ON:
if (!(dwFlags & MCI_TEST))
dwRet = DeviceMute(npMCI, FALSE);
break;
case MCI_SET_OFF:
if (!(dwFlags & MCI_TEST))
dwRet = DeviceMute(npMCI, TRUE);
break;
case MCI_SET_ON | MCI_SET_OFF:
dwRet = MCIERR_FLAGS_NOT_COMPATIBLE;
break;
default:
if (!(dwFlags & MCI_DGV_SETAUDIO_ITEM))
dwRet = MCIERR_MISSING_PARAMETER;
break;
}
return dwRet;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicSetVideo | This function sets various Video options.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the set video message.
*
* @parm LPMCI_SET_PARMS | lpSet | Parameters for the set video message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicSetVideo (NPMCIGRAPHIC npMCI,
DWORD dwFlags, LPMCI_DGV_SETVIDEO_PARMS lpSet)
{
DWORD dwRet = 0L;
if (dwFlags & (MCI_DGV_SETVIDEO_OVER |
MCI_DGV_SETVIDEO_RECORD |
MCI_DGV_SETVIDEO_SRC_NUMBER |
MCI_DGV_SETVIDEO_QUALITY |
MCI_DGV_SETVIDEO_ALG |
MCI_DGV_SETVIDEO_STILL |
MCI_DGV_SETVIDEO_CLOCKTIME
))
return MCIERR_UNSUPPORTED_FUNCTION;
if (dwFlags & MCI_DGV_SETVIDEO_ITEM) {
switch (lpSet->dwItem) {
case MCI_DGV_SETVIDEO_PALHANDLE:
if (dwFlags & MCI_DGV_SETVIDEO_VALUE) {
if (lpSet->dwValue &&
lpSet->dwValue != MCI_AVI_SETVIDEO_PALETTE_HALFTONE &&
#if 1
!IsGDIObject((HPALETTE) lpSet->dwValue))
#else
GetObjectType((HPALETTE) lpSet->dwValue) != OBJ_PAL)
#endif
return MCIERR_AVI_BADPALETTE;
}
if (!(dwFlags & MCI_TEST))
dwRet = DeviceSetPalette(npMCI,
((dwFlags & MCI_DGV_SETVIDEO_VALUE) ?
(HPALETTE) lpSet->dwValue : NULL));
break;
case MCI_DGV_SETVIDEO_STREAM:
if (!(dwFlags & MCI_DGV_SETVIDEO_VALUE))
return MCIERR_UNSUPPORTED_FUNCTION;
if (lpSet->dwValue == 0 ||
lpSet->dwValue > (DWORD)npMCI->nVideoStreams + npMCI->nOtherStreams)
return MCIERR_OUTOFRANGE;
if (dwFlags & MCI_SET_ON)
DPF(("SetVideoStream to #%d on\n", (int)lpSet->dwValue));
else if (dwFlags & MCI_SET_OFF)
DPF(("SetVideoStream to #%d off\n", (int)lpSet->dwValue));
else
DPF(("SetVideoStream to #%d\n", (int)lpSet->dwValue));
if (!(dwFlags & MCI_TEST)) {
dwRet = DeviceSetVideoStream(npMCI, (UINT)lpSet->dwValue,
!(dwFlags & MCI_SET_OFF));
}
break;
case MCI_AVI_SETVIDEO_DRAW_PROCEDURE:
if (DeviceMode(npMCI) != MCI_MODE_STOP)
return MCIERR_UNSUPPORTED_FUNCTION;
if (npMCI->hicDrawDefault) {
if (npMCI->hicDrawDefault != (HIC) -1)
ICClose(npMCI->hicDrawDefault);
npMCI->hicDrawDefault = 0;
npMCI->dwFlags &= ~(MCIAVI_USERDRAWPROC);
}
if (lpSet->dwValue) {
if (IsBadCodePtr((FARPROC) lpSet->dwValue)) {
DPF(("Bad code pointer!!!!\n"));
return MCIERR_OUTOFRANGE; //!!!MCIERR_BAD_PARAM;
}
npMCI->hicDrawDefault = ICOpenFunction(streamtypeVIDEO,
FOURCC_AVIDraw,ICMODE_DRAW,(FARPROC) lpSet->dwValue);
if (!npMCI->hicDrawDefault) {
return MCIERR_INTERNAL;
}
DPF(("Successfully set new draw procedure....\n"));
npMCI->dwFlags |= MCIAVI_USERDRAWPROC;
}
npMCI->dwFlags |= MCIAVI_NEEDDRAWBEGIN;
InvalidateRect(npMCI->hwnd, NULL, FALSE);
return 0;
default:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
}
} else if (dwFlags & (MCI_SET_ON | MCI_SET_OFF)) {
switch (dwFlags & (MCI_SET_ON | MCI_SET_OFF)) {
case MCI_SET_ON:
if (!(dwFlags & MCI_TEST)) {
InvalidateRect(npMCI->hwnd, NULL, FALSE);
npMCI->dwFlags |= MCIAVI_SHOWVIDEO;
}
break;
case MCI_SET_OFF:
if (!(dwFlags & MCI_TEST))
npMCI->dwFlags &= ~(MCIAVI_SHOWVIDEO);
break;
case MCI_SET_ON | MCI_SET_OFF:
dwRet = MCIERR_FLAGS_NOT_COMPATIBLE;
break;
}
} else
dwRet = MCIERR_MISSING_PARAMETER;
return dwRet;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicSignal | This function sets signals.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the set PositionAdvise message.
*
* @parm LPMCI_SIGNAL_PARMS | lpSignal | Parameters for the signal
* message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicSignal(NPMCIGRAPHIC npMCI,
DWORD dwFlags, LPMCI_DGV_SIGNAL_PARMS lpSignal)
{
DWORD dwRet = 0L;
DWORD dwUser;
DWORD dwPosition;
DWORD dwPeriod;
dwUser = (dwFlags & MCI_DGV_SIGNAL_USERVAL) ? lpSignal->dwUserParm : 0L;
if (dwFlags & MCI_DGV_SIGNAL_CANCEL) {
if (dwFlags & (MCI_DGV_SIGNAL_AT |
MCI_DGV_SIGNAL_EVERY |
MCI_DGV_SIGNAL_POSITION))
return MCIERR_FLAGS_NOT_COMPATIBLE;
if (!npMCI->dwSignals)
return MCIERR_NONAPPLICABLE_FUNCTION;
if (dwUser && (npMCI->signal.dwUserParm != dwUser))
return MCIERR_NONAPPLICABLE_FUNCTION;
if (!(dwFlags & MCI_TEST))
--npMCI->dwSignals;
} else {
if ((npMCI->dwSignals != 0) && (dwUser != npMCI->signal.dwUserParm)) {
/* !!! Should we allow more than one signal? */
return MCIERR_DGV_DEVICE_LIMIT;
}
if (dwFlags & MCI_DGV_SIGNAL_AT) {
/* Use position passed in */
dwPosition = ConvertToFrames(npMCI, lpSignal->dwPosition);
if (dwPosition > (DWORD) npMCI->lFrames)
return MCIERR_OUTOFRANGE;
} else {
/* Get current position */
DevicePosition(npMCI, (LPLONG) &dwPosition);
}
if (dwFlags & MCI_DGV_SIGNAL_EVERY) {
dwPeriod = (DWORD) ConvertToFrames(npMCI, lpSignal->dwPeriod);
if (dwPeriod == 0 || (dwPeriod > (DWORD) npMCI->lFrames))
return MCIERR_OUTOFRANGE;
} else {
/* It's a one-time signal */
dwPeriod = 0L;
}
if (dwFlags & MCI_TEST)
return 0;
npMCI->signal.dwPosition = dwPosition;
npMCI->signal.dwPeriod = dwPeriod;
npMCI->signal.dwUserParm = dwUser;
npMCI->signal.dwCallback = lpSignal->dwCallback;
npMCI->dwSignalFlags = dwFlags;
/* The signal isn't really activated until we do this. */
if (!npMCI->dwSignals)
++npMCI->dwSignals;
}
return 0L;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicList | This function supports the MCI_LIST command.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the List message.
*
* @parm LPMCI_DGV_LIST_PARMS | lpList | Parameters for the list message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicList(NPMCIGRAPHIC npMCI,
DWORD dwFlags, LPMCI_DGV_LIST_PARMS lpList)
{
return MCIERR_UNSUPPORTED_FUNCTION;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicGetDevCaps | This function returns device
* capabilities
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the GetDevCaps message.
*
* @parm LPMCI_GETDEVCAPS_PARMS | lpCaps | Parameters for the GetDevCaps
* message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicGetDevCaps (NPMCIGRAPHIC npMCI,
DWORD dwFlags, LPMCI_GETDEVCAPS_PARMS lpCaps )
{
DWORD dwRet = 0L;
if (dwFlags & MCI_GETDEVCAPS_ITEM)
{
switch (lpCaps->dwItem)
{
case MCI_GETDEVCAPS_CAN_RECORD:
case MCI_GETDEVCAPS_CAN_EJECT:
case MCI_GETDEVCAPS_CAN_SAVE:
case MCI_DGV_GETDEVCAPS_CAN_LOCK:
case MCI_DGV_GETDEVCAPS_CAN_STR_IN:
case MCI_DGV_GETDEVCAPS_CAN_FREEZE:
case MCI_DGV_GETDEVCAPS_HAS_STILL:
lpCaps->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_DGV_GETDEVCAPS_CAN_REVERSE:
case MCI_GETDEVCAPS_CAN_PLAY:
case MCI_GETDEVCAPS_HAS_AUDIO:
case MCI_GETDEVCAPS_HAS_VIDEO:
case MCI_GETDEVCAPS_USES_FILES:
case MCI_GETDEVCAPS_COMPOUND_DEVICE:
case MCI_DGV_GETDEVCAPS_PALETTES:
case MCI_DGV_GETDEVCAPS_CAN_STRETCH:
case MCI_DGV_GETDEVCAPS_CAN_TEST:
lpCaps->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_GETDEVCAPS_DEVICE_TYPE:
lpCaps->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_DIGITAL_VIDEO,
MCI_DEVTYPE_DIGITAL_VIDEO);
dwRet = MCI_RESOURCE_RETURNED;
break;
case MCI_DGV_GETDEVCAPS_MAX_WINDOWS:
case MCI_DGV_GETDEVCAPS_MAXIMUM_RATE:
case MCI_DGV_GETDEVCAPS_MINIMUM_RATE:
default:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
}
}
else
dwRet = MCIERR_MISSING_PARAMETER;
if ((dwFlags & MCI_TEST) && (LOWORD(dwRet) == 0)) {
/* There is no error, but the test flag is on. Return as little
** as possible.
*/
dwRet = 0;
lpCaps->dwReturn = 0;
}
return (dwRet);
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicWindow | This function controls the stage window
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the window message.
*
* @parm LPMCI_DGV_WINDOW_PARMS | lpPlay | Parameters for the window message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicWindow (NPMCIGRAPHIC npMCI, DWORD dwFlags,
LPMCI_DGV_WINDOW_PARMS lpWindow)
{
DWORD dwRet = 0L;
int i = 0;
HWND hWndNew;
if (dwFlags & MCI_DGV_WINDOW_HWND) {
// Set a new stage window. If the parameter is NULL, then
// use the default window. Otherwise, hide the default
// window and use the given window handle.
if (!lpWindow->hWnd)
hWndNew = npMCI->hwndDefault;
else
hWndNew = lpWindow->hWnd;
if (!IsWindow(hWndNew))
return MCIERR_NO_WINDOW;
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
// only change if the new window handle is different from the current
// stage window handle
if (hWndNew != npMCI->hwnd) {
dwRet = DeviceSetWindow(npMCI, hWndNew);
if (npMCI->hwnd != npMCI->hwndDefault &&
IsWindow(npMCI->hwndDefault))
ShowWindow(npMCI->hwndDefault, SW_HIDE);
}
}
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return dwRet;
if (!dwRet) {
if (IsWindow(npMCI->hwnd)) {
if (dwFlags & MCI_DGV_WINDOW_STATE)
ShowWindow (npMCI->hwnd, lpWindow->nCmdShow);
if (dwFlags & MCI_DGV_WINDOW_TEXT)
SetWindowText(npMCI->hwnd, lpWindow->lpstrText);
} else
dwRet = MCIERR_NO_WINDOW;
}
return dwRet;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicPut | This function sets the offset and extent
* of the animation within the client area of the stage window.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the put message.
*
* @parm LPMCI_DGV_RECT_PARMS | lpDestination | Parameters for the
* destination message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicPut ( NPMCIGRAPHIC npMCI,
DWORD dwFlags, LPMCI_DGV_RECT_PARMS lpParms)
{
BOOL frc;
RECT rc;
if (dwFlags & (MCI_DGV_PUT_FRAME | MCI_DGV_PUT_VIDEO))
return MCIERR_UNSUPPORTED_FUNCTION;
frc = (dwFlags & MCI_DGV_RECT) == MCI_DGV_RECT;
if (!IsWindow(npMCI->hwnd))
return MCIERR_NO_WINDOW;
switch (dwFlags & (MCI_DGV_PUT_SOURCE | MCI_DGV_PUT_DESTINATION |
MCI_DGV_PUT_WINDOW)) {
case 0L:
return MCIERR_MISSING_PARAMETER;
case MCI_DGV_PUT_SOURCE:
// If a rectangle is supplied, use it.
if (frc) {
rc.left = lpParms->ptOffset.x;
rc.top = lpParms->ptOffset.y;
rc.right = lpParms->ptOffset.x + lpParms->ptExtent.x;
rc.bottom = lpParms->ptOffset.y + lpParms->ptExtent.y;
if (lpParms->ptExtent.x <= 0) {
rc.right = rc.left + (npMCI->rcDest.right - npMCI->rcDest.left);
}
if (lpParms->ptExtent.y <= 0) {
rc.bottom = rc.top + (npMCI->rcDest.bottom - npMCI->rcDest.top);
}
} else {
/* Reset to default */
rc = npMCI->rcMovie;
}
break;
case MCI_DGV_PUT_DESTINATION:
// If a rectangle is supplied, use it.
if (frc) {
rc.left = lpParms->ptOffset.x;
rc.top = lpParms->ptOffset.y;
rc.right = lpParms->ptOffset.x + lpParms->ptExtent.x;
rc.bottom = lpParms->ptOffset.y + lpParms->ptExtent.y;
if (lpParms->ptExtent.x <= 0) {
rc.right = rc.left + (npMCI->rcDest.right - npMCI->rcDest.left);
}
if (lpParms->ptExtent.y <= 0) {
rc.bottom = rc.top + (npMCI->rcDest.bottom - npMCI->rcDest.top);
}
} else {
/* Reset to size of stage window */
GetClientRect(npMCI->hwnd, &rc);
}
break;
case MCI_DGV_PUT_WINDOW:
if (dwFlags & MCI_TEST)
return 0L;
// De-minimize their window, so we don't end up with
// a giant icon....
if (IsIconic(npMCI->hwnd))
ShowWindow(npMCI->hwnd, SW_RESTORE);
// If a rectangle is supplied, use it.
if (frc) {
RECT rcOld;
rc.left = lpParms->ptOffset.x;
rc.right = lpParms->ptOffset.x + lpParms->ptExtent.x;
rc.top = lpParms->ptOffset.y;
rc.bottom = lpParms->ptOffset.y + lpParms->ptExtent.y;
if (dwFlags & MCI_DGV_PUT_CLIENT) {
AdjustWindowRect(&rc,
GetWindowLong(npMCI->hwnd, GWL_STYLE),
FALSE);
}
// Default to just moving if width, height == 0....
GetWindowRect(npMCI->hwnd, &rcOld);
if (lpParms->ptExtent.x <= 0) {
rc.right = rc.left + (rcOld.right - rcOld.left);
}
if (lpParms->ptExtent.y <= 0) {
rc.bottom = rc.top + (rcOld.bottom - rcOld.top);
}
MoveWindow(npMCI->hwnd,
rc.left, rc.top,
rc.right - rc.left, rc.bottom - rc.top, TRUE);
} else {
// !!! What should we do if there's no rectangle?
/* Reset to "natural" size? */
rc = npMCI->rcMovie;
if (npMCI->dwOptionFlags & MCIAVIO_ZOOMBY2)
SetRect(&rc, 0, 0, rc.right*2, rc.bottom*2);
AdjustWindowRect(&rc, GetWindowLong(npMCI->hwnd, GWL_STYLE),
FALSE);
SetWindowPos(npMCI->hwnd, NULL, 0, 0,
rc.right - rc.left, rc.bottom - rc.top,
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
}
// Premiere 1.0 depends on the window always being visible
// after a PUT_WINDOW command. Make it so.
ShowWindow(npMCI->hwnd, SW_RESTORE);
return 0L;
default:
return MCIERR_FLAGS_NOT_COMPATIBLE;
}
if (dwFlags & MCI_DGV_PUT_CLIENT)
return MCIERR_FLAGS_NOT_COMPATIBLE;
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
return DevicePut(npMCI, &rc, dwFlags);
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicWhere | This function returns the current
* source and destination rectangles, in offset/extent form.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the query source message.
*
* @parm LPMCI_DGV_RECT_PARMS | lpParms | Parameters for the message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicWhere(NPMCIGRAPHIC npMCI, DWORD dwFlags,
LPMCI_DGV_RECT_PARMS lpParms)
{
RECT rc;
if (dwFlags & (MCI_DGV_WHERE_FRAME | MCI_DGV_WHERE_VIDEO))
return MCIERR_UNSUPPORTED_FUNCTION;
// !!! WHERE_WINDOW?
switch (dwFlags & (MCI_DGV_WHERE_SOURCE | MCI_DGV_WHERE_DESTINATION |
MCI_DGV_WHERE_WINDOW)) {
case 0L:
return MCIERR_MISSING_PARAMETER;
case MCI_DGV_WHERE_SOURCE:
if (dwFlags & MCI_DGV_WHERE_MAX) {
lpParms->ptOffset.x = npMCI->rcMovie.left;
lpParms->ptOffset.y = npMCI->rcMovie.top;
lpParms->ptExtent.x = npMCI->rcMovie.right - npMCI->rcMovie.left;
lpParms->ptExtent.y = npMCI->rcMovie.bottom - npMCI->rcMovie.top;
} else {
lpParms->ptOffset.x = npMCI->rcSource.left;
lpParms->ptOffset.y = npMCI->rcSource.top;
lpParms->ptExtent.x = npMCI->rcSource.right - npMCI->rcSource.left;
lpParms->ptExtent.y = npMCI->rcSource.bottom - npMCI->rcSource.top;
}
break;
case MCI_DGV_WHERE_DESTINATION:
if (dwFlags & MCI_DGV_WHERE_MAX) {
/* Return size of window */
GetClientRect(npMCI->hwnd, &rc);
lpParms->ptOffset.x = 0;
lpParms->ptOffset.y = 0;
lpParms->ptExtent.x = rc.right;
lpParms->ptExtent.y = rc.bottom;
} else {
/* Return current destination size */
lpParms->ptOffset.x = npMCI->rcDest.left;
lpParms->ptOffset.y = npMCI->rcDest.top;
lpParms->ptExtent.x = npMCI->rcDest.right - npMCI->rcDest.left;
lpParms->ptExtent.y = npMCI->rcDest.bottom - npMCI->rcDest.top;
}
break;
case MCI_DGV_WHERE_WINDOW:
if (dwFlags & MCI_DGV_WHERE_MAX) {
/* Return maximum size of window */
GetClientRect(npMCI->hwnd, &rc);
lpParms->ptOffset.x = 0;
lpParms->ptOffset.y = 0;
lpParms->ptExtent.x = GetSystemMetrics(SM_CXSCREEN);
lpParms->ptExtent.y = GetSystemMetrics(SM_CYSCREEN);
} else {
/* Return size of window */
GetWindowRect(npMCI->hwnd, &rc);
lpParms->ptOffset.x = rc.left;
lpParms->ptOffset.y = rc.top;
lpParms->ptExtent.x = rc.right - rc.left;
lpParms->ptExtent.y = rc.bottom - rc.top;
}
break;
default:
return MCIERR_FLAGS_NOT_COMPATIBLE;
}
return 0L;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicRealize | This function realizes the current palette
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicRealize(NPMCIGRAPHIC npMCI, DWORD dwFlags)
{
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
npMCI->fForceBackground = (dwFlags & MCI_DGV_REALIZE_BKGD) != 0;
return DeviceRealize(npMCI);
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | GraphicUpdate | This function refreshes the current frame.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwFlags | Flags for the message.
*
* @parm LPMCI_DGV_UPDATE_PARMS | lpParms | Parameters for the message.
*
* @rdesc Returns an MCI error code.
*
***************************************************************************/
DWORD NEAR PASCAL GraphicUpdate(NPMCIGRAPHIC npMCI, DWORD dwFlags,
LPMCI_DGV_UPDATE_PARMS lpParms)
{
RECT rc;
rc.left = lpParms->ptOffset.x;
rc.top = lpParms->ptOffset.y;
rc.right = lpParms->ptOffset.x + lpParms->ptExtent.x;
rc.bottom = lpParms->ptOffset.y + lpParms->ptExtent.y;
if (!(dwFlags & MCI_DGV_UPDATE_HDC)) {
InvalidateRect(npMCI->hwnd, (dwFlags & MCI_DGV_RECT) ? &rc : NULL, TRUE);
UpdateWindow(npMCI->hwnd);
return 0;
}
/* If the test flag is set, return without doing anything. */
/* Question: do we have to check for more possible errors? */
if (dwFlags & MCI_TEST)
return 0L;
/* It's ok to pass a NULL rect to DeviceUpdate() */
#ifndef WIN32
#pragma message("!!! Fix update parms!")
#endif
return DeviceUpdate (npMCI, dwFlags, lpParms->hDC, (dwFlags & MCI_DGV_RECT) ? &rc : NULL);
}
DWORD FAR PASCAL GraphicConfig(NPMCIGRAPHIC npMCI, DWORD dwFlags)
{
DWORD dwOptions = npMCI->dwOptionFlags;
if (!(dwFlags & MCI_TEST)) {
gfEvil++;
if (ConfigDialog(NULL, npMCI)) {
#ifdef DEBUG
//
// in DEBUG always reset the dest rect because the user may
// have played with the DEBUG DrawDib options and we will
// need to call DrawDibBegin() again.
//
if (TRUE) {
#else
if ((npMCI->dwOptionFlags & (MCIAVIO_STUPIDMODE|MCIAVIO_ZOOMBY2))
!= (dwOptions & (MCIAVIO_STUPIDMODE|MCIAVIO_ZOOMBY2)) ) {
#endif
npMCI->lFrameDrawn = (- (LONG) npMCI->wEarlyRecords) - 1;
SetWindowToDefaultSize(npMCI);
SetRectEmpty(&npMCI->rcDest); //This will force a change!
ResetDestRect(npMCI);
}
}
else {
npMCI->dwOptionFlags = dwOptions;
}
gfEvil--;
}
return 0L;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | mciSpecial | This function handles all the MCI
* commands that don't require instance data such as open.
*
* @parm UINT | wDeviceID | The MCI device ID
*
* @parm UINT | wMessage | The requested action to be performed.
*
* @parm DWORD | dwFlags | Flags for the message.
*
* @parm DWORD | lpParms | Parameters for this message.
*
* @rdesc Error Constant. 0L on success
*
***************************************************************************/
DWORD NEAR PASCAL mciSpecial (UINT wDeviceID, UINT wMessage, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
{
NPMCIGRAPHIC npMCI = 0L;
DWORD dwRet;
/* since there in no instance block, there is no saved notification */
/* to abort. */
switch (wMessage) {
case MCI_OPEN_DRIVER:
if (dwFlags & (MCI_OPEN_ELEMENT | MCI_OPEN_ELEMENT_ID))
dwRet = GraphicOpen (&npMCI, dwFlags,
(LPMCI_DGV_OPEN_PARMS) lpParms, wDeviceID);
else
dwRet = 0L;
mciSetDriverData (wDeviceID, (UINT)npMCI);
break;
case MCI_GETDEVCAPS:
dwRet = GraphicGetDevCaps(NULL, dwFlags,
(LPMCI_GETDEVCAPS_PARMS)lpParms);
break;
case MCI_CONFIGURE:
if (!(dwFlags & MCI_TEST))
ConfigDialog(NULL, NULL);
dwRet = 0L;
break;
case MCI_INFO:
dwRet = GraphicInfo(NULL, dwFlags, (LPMCI_DGV_INFO_PARMS)lpParms);
break;
case MCI_CLOSE_DRIVER:
dwRet = 0L;
break;
default:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
}
GraphicImmediateNotify (wDeviceID, lpParms, dwFlags, dwRet);
return (dwRet);
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | mciDriverEntry | This function is the MCI handler
*
* @parm UINT | wDeviceID | The MCI device ID
*
* @parm UINT | wMessage | The requested action to be performed.
*
* @parm DWORD | dwFlags | Flags for the message.
*
* @parm DWORD | lpParms | Parameters for this message.
*
* @rdesc Error Constant. 0L on success
*
***************************************************************************/
DWORD PASCAL mciDriverEntry (UINT wDeviceID, UINT wMessage, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
{
NPMCIGRAPHIC npMCI = 0L;
DWORD dwRet = MCIERR_UNRECOGNIZED_COMMAND;
BOOL fDelayed = FALSE;
BOOL fNested = FALSE;
/* All current commands require a parameter block. */
if (!lpParms && (dwFlags & MCI_NOTIFY))
return (MCIERR_MISSING_PARAMETER);
npMCI = (NPMCIGRAPHIC) (UINT)mciGetDriverData(wDeviceID);
if (!npMCI)
return mciSpecial(wDeviceID, wMessage, dwFlags, lpParms);
/*
* grab this device's critical section
*/
EnterCrit(npMCI);
if (npMCI->wMessageCurrent) {
fNested = TRUE;
if (wMessage != MCI_STATUS && wMessage != MCI_GETDEVCAPS &&
wMessage != MCI_INFO) {
DPF(("Warning!!!!!\n"));
DPF(("Warning!!!!! MCIAVI reentered: received %x while processing %x\n", wMessage, npMCI->wMessageCurrent));
DPF(("Warning!!!!!\n"));
DPF(("Warning!!!!!\n"));
// Assert(0);
// LeaveCrit(npMCI);
// return MCIERR_DEVICE_NOT_READY;
}
} else
npMCI->wMessageCurrent = wMessage;
switch (wMessage) {
case MCI_CLOSE_DRIVER:
/* Closing the driver causes any currently saved notifications */
/* to abort. */
GraphicDelayedNotify(npMCI, MCI_NOTIFY_ABORTED);
// note that GraphicClose will release and delete the critsec
dwRet = GraphicClose(npMCI);
mciSetDriverData(wDeviceID, 0L);
npMCI = NULL;
break;
case MCI_PLAY:
dwRet = GraphicPlay(npMCI, dwFlags, (LPMCI_PLAY_PARMS)lpParms);
fDelayed = TRUE;
break;
case MCI_CUE:
dwRet = GraphicCue(npMCI, dwFlags, (LPMCI_DGV_CUE_PARMS)lpParms);
fDelayed = TRUE;
break;
case MCI_STEP:
dwRet = GraphicStep(npMCI, dwFlags, (LPMCI_DGV_STEP_PARMS)lpParms);
fDelayed = TRUE;
break;
case MCI_STOP:
dwRet = GraphicStop(npMCI, dwFlags, lpParms);
break;
case MCI_SEEK:
dwRet = GraphicSeek (npMCI, dwFlags, (LPMCI_SEEK_PARMS)lpParms);
fDelayed = TRUE;
break;
case MCI_PAUSE:
dwRet = GraphicPause(npMCI, dwFlags, lpParms);
fDelayed = TRUE;
break;
case MCI_RESUME:
dwRet = GraphicResume(npMCI, dwFlags, lpParms);
fDelayed = TRUE;
break;
case MCI_SET:
dwRet = GraphicSet(npMCI, dwFlags,
(LPMCI_DGV_SET_PARMS)lpParms);
break;
case MCI_STATUS:
dwRet = GraphicStatus(npMCI, dwFlags,
(LPMCI_DGV_STATUS_PARMS)lpParms);
break;
case MCI_INFO:
dwRet = GraphicInfo (npMCI, dwFlags, (LPMCI_DGV_INFO_PARMS)lpParms);
break;
case MCI_GETDEVCAPS:
dwRet = GraphicGetDevCaps(npMCI, dwFlags, (LPMCI_GETDEVCAPS_PARMS)lpParms);
break;
case MCI_REALIZE:
dwRet = GraphicRealize(npMCI, dwFlags);
break;
case MCI_UPDATE:
dwRet = GraphicUpdate(npMCI, dwFlags, (LPMCI_DGV_UPDATE_PARMS)lpParms);
break;
case MCI_WINDOW:
dwRet = GraphicWindow(npMCI, dwFlags, (LPMCI_DGV_WINDOW_PARMS)lpParms);
break;
case MCI_PUT:
dwRet = GraphicPut(npMCI, dwFlags, (LPMCI_DGV_RECT_PARMS)lpParms);
break;
case MCI_WHERE:
dwRet = GraphicWhere(npMCI, dwFlags, (LPMCI_DGV_RECT_PARMS)lpParms);
break;
case MCI_CONFIGURE:
dwRet = GraphicConfig(npMCI, dwFlags);
break;
case MCI_SETAUDIO:
dwRet = GraphicSetAudio(npMCI, dwFlags,
(LPMCI_DGV_SETAUDIO_PARMS) lpParms);
break;
case MCI_SETVIDEO:
dwRet = GraphicSetVideo(npMCI, dwFlags,
(LPMCI_DGV_SETVIDEO_PARMS) lpParms);
break;
case MCI_SIGNAL:
dwRet = GraphicSignal(npMCI, dwFlags,
(LPMCI_DGV_SIGNAL_PARMS) lpParms);
break;
case MCI_LIST:
dwRet = GraphicList(npMCI, dwFlags,
(LPMCI_DGV_LIST_PARMS) lpParms);
break;
case MCI_LOAD:
dwRet = GraphicLoad(npMCI, dwFlags,
(LPMCI_DGV_LOAD_PARMS) lpParms);
break;
case MCI_RECORD:
case MCI_SAVE:
case MCI_CUT:
case MCI_COPY:
case MCI_PASTE:
case MCI_UNDO:
case MCI_DELETE:
case MCI_CAPTURE:
case MCI_QUALITY:
case MCI_MONITOR:
case MCI_RESERVE:
case MCI_FREEZE:
case MCI_UNFREEZE:
dwRet = MCIERR_UNSUPPORTED_FUNCTION;
break;
/* Do we need this case? */
default:
dwRet = MCIERR_UNRECOGNIZED_COMMAND;
break;
}
if (!fDelayed || (dwFlags & MCI_TEST)) {
/* We haven't processed the notify yet. */
if (npMCI && (dwFlags & MCI_NOTIFY) && (!LOWORD(dwRet)))
/* Throw away the old notify */
GraphicDelayedNotify(npMCI, MCI_NOTIFY_SUPERSEDED);
/* And send the new one out immediately. */
GraphicImmediateNotify(wDeviceID, lpParms, dwFlags, dwRet);
}
/* If there's an error, don't save the callback.... */
if (fDelayed && dwRet != 0 && (dwFlags & MCI_NOTIFY))
npMCI->hCallback = 0;
//
// see if we need to tell the DRAW device about moving.
// MPlayer is sending the status and position command alot
// so this is a "timer"
//
// !!!do we need to do it this often?
//
if (npMCI && (npMCI->dwFlags & MCIAVI_WANTMOVE))
CheckWindowMove(npMCI, FALSE);
if (npMCI && !fNested)
npMCI->wMessageCurrent = 0;
// free critical section for this device - if we haven't deleted it
// GraphicClose may have released and deleted it if we were deleting
// the device instance.
if (npMCI) {
LeaveCrit(npMCI);
}
return dwRet;
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api LONG | ConvertToFrames | Convert from the current time format into
* frames.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm DWORD | dwTime | Input time.
*
***************************************************************************/
STATICFN LONG NEAR PASCAL ConvertToFrames(NPMCIGRAPHIC npMCI, DWORD dwTime)
{
if (npMCI->dwTimeFormat == MCI_FORMAT_FRAMES) {
return (LONG) dwTime;
} else {
if (npMCI->dwMicroSecPerFrame > 1000) {
/* This needs to round down--muldiv32 likes to round off. */
return (LONG) muldivrd32(dwTime, 1000L, npMCI->dwMicroSecPerFrame);
} else {
return (LONG) muldivru32(dwTime, 1000L, npMCI->dwMicroSecPerFrame);
}
}
}
/***************************************************************************
*
* @doc INTERNAL MCIAVI
*
* @api DWORD | ConvertFromFrames | Convert from frames into the current
* time format.
*
* @parm NPMCIGRAPHIC | npMCI | Near pointer to instance data block
*
* @parm LONG | lFrame | Frame number to convert.
*
***************************************************************************/
DWORD NEAR PASCAL ConvertFromFrames(NPMCIGRAPHIC npMCI, LONG lFrame)
{
if (npMCI->dwTimeFormat == MCI_FORMAT_FRAMES) {
return (DWORD)lFrame;
} else {
if (npMCI->dwMicroSecPerFrame > 1000)
return muldivru32(lFrame, npMCI->dwMicroSecPerFrame, 1000L);
else
return muldivrd32(lFrame, npMCI->dwMicroSecPerFrame, 1000L);
}
}