mirror of
https://github.com/reactos/wine.git
synced 2024-11-26 21:20:25 +00:00
1435 lines
44 KiB
C
1435 lines
44 KiB
C
/*
|
|
* Copyright 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
|
|
*
|
|
* FIXME:
|
|
* Add support for all remaining MCI_ commands and MCIWNDM_ messages.
|
|
* Add support for MCIWNDF_RECORD.
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "winnls.h"
|
|
#include "wingdi.h"
|
|
#include "winuser.h"
|
|
#include "winreg.h"
|
|
#include "winternl.h"
|
|
#include "vfw.h"
|
|
#include "digitalv.h"
|
|
#include "commctrl.h"
|
|
#include "wine/unicode.h"
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(mci);
|
|
|
|
extern HMODULE MSVFW32_hModule;
|
|
static const WCHAR mciWndClassW[] = {'M','C','I','W','n','d','C','l','a','s','s',0};
|
|
|
|
typedef struct
|
|
{
|
|
DWORD dwStyle;
|
|
MCIDEVICEID mci;
|
|
HDRVR hdrv;
|
|
int alias;
|
|
UINT dev_type;
|
|
UINT mode;
|
|
long position;
|
|
SIZE size; /* size of the original frame rect */
|
|
int zoom;
|
|
LPWSTR lpName;
|
|
HWND hWnd, hwndOwner;
|
|
UINT uTimer;
|
|
MCIERROR lasterror;
|
|
WCHAR return_string[128];
|
|
WORD active_timer, inactive_timer;
|
|
} MCIWndInfo;
|
|
|
|
static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
|
|
|
|
#define CTL_PLAYSTOP 0x3200
|
|
#define CTL_MENU 0x3201
|
|
#define CTL_TRACKBAR 0x3202
|
|
|
|
/***********************************************************************
|
|
* MCIWndRegisterClass [MSVFW32.@]
|
|
*
|
|
* NOTE: Native always uses its own hInstance
|
|
*/
|
|
BOOL VFWAPIV MCIWndRegisterClass(void)
|
|
{
|
|
WNDCLASSW wc;
|
|
|
|
/* Since we are going to register a class belonging to MSVFW32
|
|
* and later we will create windows with a different hInstance
|
|
* CS_GLOBALCLASS is needed. And because the second attempt
|
|
* to register a global class will fail we need to test whether
|
|
* the class was already registered.
|
|
*/
|
|
wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC | CS_GLOBALCLASS;
|
|
wc.lpfnWndProc = MCIWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = sizeof(MCIWndInfo*);
|
|
wc.hInstance = MSVFW32_hModule;
|
|
wc.hIcon = 0;
|
|
wc.hCursor = LoadCursorW(0, MAKEINTRESOURCEW(IDC_ARROW));
|
|
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = mciWndClassW;
|
|
|
|
if (RegisterClassW(&wc)) return TRUE;
|
|
if (GetLastError() == ERROR_CLASS_ALREADY_EXISTS) return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* MCIWndCreateW [MSVFW32.@]
|
|
*/
|
|
HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance,
|
|
DWORD dwStyle, LPCWSTR szFile)
|
|
{
|
|
TRACE("%p %p %x %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile));
|
|
|
|
MCIWndRegisterClass();
|
|
|
|
if (!hInstance) hInstance = GetModuleHandleW(0);
|
|
|
|
if (hwndParent)
|
|
dwStyle |= WS_VISIBLE | WS_BORDER /*| WS_CHILD*/;
|
|
else
|
|
dwStyle |= WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
|
|
|
|
return CreateWindowExW(0, mciWndClassW, NULL,
|
|
dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
|
|
0, 0, 300, 0,
|
|
hwndParent, 0, hInstance, (LPVOID)szFile);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* MCIWndCreate [MSVFW32.@]
|
|
* MCIWndCreateA [MSVFW32.@]
|
|
*/
|
|
HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance,
|
|
DWORD dwStyle, LPCSTR szFile)
|
|
{
|
|
HWND ret;
|
|
UNICODE_STRING fileW;
|
|
|
|
if (szFile)
|
|
RtlCreateUnicodeStringFromAsciiz(&fileW, szFile);
|
|
else
|
|
fileW.Buffer = NULL;
|
|
|
|
ret = MCIWndCreateW(hwndParent, hInstance, dwStyle, fileW.Buffer);
|
|
|
|
RtlFreeUnicodeString(&fileW);
|
|
return ret;
|
|
}
|
|
|
|
static inline void MCIWND_notify_mode(MCIWndInfo *mwi)
|
|
{
|
|
if (mwi->dwStyle & MCIWNDF_NOTIFYMODE)
|
|
{
|
|
UINT new_mode = SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0);
|
|
if (new_mode != mwi->mode)
|
|
{
|
|
mwi->mode = new_mode;
|
|
SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMODE, (WPARAM)mwi->hWnd, new_mode);
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void MCIWND_notify_pos(MCIWndInfo *mwi)
|
|
{
|
|
if (mwi->dwStyle & MCIWNDF_NOTIFYPOS)
|
|
{
|
|
long new_pos = SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 0, 0);
|
|
if (new_pos != mwi->position)
|
|
{
|
|
mwi->position = new_pos;
|
|
SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYPOS, (WPARAM)mwi->hWnd, new_pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void MCIWND_notify_size(MCIWndInfo *mwi)
|
|
{
|
|
if (mwi->dwStyle & MCIWNDF_NOTIFYSIZE)
|
|
SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYSIZE, (WPARAM)mwi->hWnd, 0);
|
|
}
|
|
|
|
static inline void MCIWND_notify_error(MCIWndInfo *mwi)
|
|
{
|
|
if (mwi->dwStyle & MCIWNDF_NOTIFYERROR)
|
|
SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYERROR, (WPARAM)mwi->hWnd, (LPARAM)mwi->lasterror);
|
|
}
|
|
|
|
static void MCIWND_UpdateState(MCIWndInfo *mwi)
|
|
{
|
|
WCHAR buffer[1024];
|
|
|
|
if (!mwi->mci)
|
|
{
|
|
/* FIXME: get this from resources */
|
|
static const WCHAR no_deviceW[] = {'N','o',' ','D','e','v','i','c','e',0};
|
|
SetWindowTextW(mwi->hWnd, no_deviceW);
|
|
return;
|
|
}
|
|
|
|
MCIWND_notify_pos(mwi);
|
|
|
|
if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
|
|
SendDlgItemMessageW(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, TRUE, mwi->position);
|
|
|
|
if (!(mwi->dwStyle & MCIWNDF_SHOWALL))
|
|
return;
|
|
|
|
if ((mwi->dwStyle & MCIWNDF_SHOWNAME) && mwi->lpName)
|
|
strcpyW(buffer, mwi->lpName);
|
|
else
|
|
*buffer = 0;
|
|
|
|
if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
|
|
{
|
|
static const WCHAR spaceW[] = {' ',0};
|
|
static const WCHAR l_braceW[] = {'(',0};
|
|
|
|
if (*buffer) strcatW(buffer, spaceW);
|
|
strcatW(buffer, l_braceW);
|
|
}
|
|
|
|
if (mwi->dwStyle & MCIWNDF_SHOWPOS)
|
|
{
|
|
WCHAR posW[64];
|
|
|
|
posW[0] = 0;
|
|
SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 64, (LPARAM)posW);
|
|
strcatW(buffer, posW);
|
|
}
|
|
|
|
if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
|
|
{
|
|
static const WCHAR dashW[] = {' ','-',' ',0};
|
|
strcatW(buffer, dashW);
|
|
}
|
|
|
|
if (mwi->dwStyle & MCIWNDF_SHOWMODE)
|
|
{
|
|
WCHAR modeW[64];
|
|
|
|
modeW[0] = 0;
|
|
SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 64, (LPARAM)modeW);
|
|
strcatW(buffer, modeW);
|
|
}
|
|
|
|
if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
|
|
{
|
|
static const WCHAR r_braceW[] = {')',0};
|
|
strcatW(buffer, r_braceW);
|
|
}
|
|
|
|
TRACE("=> '%s'\n", debugstr_w(buffer));
|
|
SetWindowTextW(mwi->hWnd, buffer);
|
|
}
|
|
|
|
static LRESULT MCIWND_Create(HWND hWnd, LPCREATESTRUCTW cs)
|
|
{
|
|
HWND hChld;
|
|
MCIWndInfo *mwi;
|
|
static const WCHAR buttonW[] = {'b','u','t','t','o','n',0};
|
|
|
|
mwi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*mwi));
|
|
if (!mwi) return -1;
|
|
|
|
SetWindowLongW(hWnd, 0, (LPARAM)mwi);
|
|
|
|
mwi->dwStyle = cs->style;
|
|
/* There is no need to show stats if there is no caption */
|
|
if ((mwi->dwStyle & WS_CAPTION) != WS_CAPTION)
|
|
mwi->dwStyle &= ~MCIWNDF_SHOWALL;
|
|
|
|
mwi->hWnd = hWnd;
|
|
mwi->hwndOwner = cs->hwndParent;
|
|
mwi->active_timer = 500;
|
|
mwi->inactive_timer = 2000;
|
|
mwi->mode = MCI_MODE_NOT_READY;
|
|
mwi->position = -1;
|
|
mwi->zoom = 100;
|
|
|
|
if (!(mwi->dwStyle & MCIWNDF_NOMENU))
|
|
{
|
|
static const WCHAR menuW[] = {'M','e','n','u',0};
|
|
|
|
hChld = CreateWindowExW(0, buttonW, menuW, WS_CHILD|WS_VISIBLE, 32, cs->cy, 32, 32,
|
|
hWnd, (HMENU)CTL_MENU, cs->hInstance, 0L);
|
|
TRACE("Get Button2: %p\n", hChld);
|
|
}
|
|
|
|
if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
|
|
{
|
|
INITCOMMONCONTROLSEX init;
|
|
static const WCHAR playW[] = {'P','l','a','y',0};
|
|
|
|
/* adding the other elements: play/stop button, menu button, status */
|
|
hChld = CreateWindowExW(0, buttonW, playW, WS_CHILD|WS_VISIBLE, 0, cs->cy, 32, 32,
|
|
hWnd, (HMENU)CTL_PLAYSTOP, cs->hInstance, 0L);
|
|
TRACE("Get Button1: %p\n", hChld);
|
|
|
|
init.dwSize = sizeof(init);
|
|
init.dwICC = ICC_BAR_CLASSES;
|
|
InitCommonControlsEx(&init);
|
|
|
|
hChld = CreateWindowExW(0, TRACKBAR_CLASSW, NULL, WS_CHILD|WS_VISIBLE, 64, cs->cy, cs->cx - 64, 32,
|
|
hWnd, (HMENU)CTL_TRACKBAR, cs->hInstance, 0L);
|
|
TRACE("Get status: %p\n", hChld);
|
|
}
|
|
|
|
/* This sets the default window size */
|
|
SendMessageW(hWnd, MCI_CLOSE, 0, 0);
|
|
|
|
if (cs->lpCreateParams)
|
|
{
|
|
LPARAM lParam;
|
|
|
|
/* MCI wnd class is prepared to be embedded as an MDI child window */
|
|
if (cs->dwExStyle & WS_EX_MDICHILD)
|
|
{
|
|
MDICREATESTRUCTW *mdics = (MDICREATESTRUCTW *)cs->lpCreateParams;
|
|
lParam = mdics->lParam;
|
|
}
|
|
else
|
|
lParam = (LPARAM)cs->lpCreateParams;
|
|
|
|
/* If it's our internal class pointer, file name is a unicode string */
|
|
if (cs->lpszClass == mciWndClassW)
|
|
SendMessageW(hWnd, MCIWNDM_OPENW, 0, lParam);
|
|
else
|
|
{
|
|
/* Otherwise let's try to figure out what string format is used */
|
|
HWND parent = cs->hwndParent;
|
|
if (!parent) parent = GetWindow(hWnd, GW_OWNER);
|
|
|
|
SendMessageW(hWnd, IsWindowUnicode(parent) ? MCIWNDM_OPENW : MCIWNDM_OPENA, 0, lParam);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void MCIWND_ToggleState(MCIWndInfo *mwi)
|
|
{
|
|
switch (SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0))
|
|
{
|
|
case MCI_MODE_NOT_READY:
|
|
case MCI_MODE_RECORD:
|
|
case MCI_MODE_SEEK:
|
|
case MCI_MODE_OPEN:
|
|
TRACE("Cannot do much...\n");
|
|
break;
|
|
|
|
case MCI_MODE_PAUSE:
|
|
SendMessageW(mwi->hWnd, MCI_RESUME, 0, 0);
|
|
break;
|
|
|
|
case MCI_MODE_PLAY:
|
|
SendMessageW(mwi->hWnd, MCI_PAUSE, 0, 0);
|
|
break;
|
|
|
|
case MCI_MODE_STOP:
|
|
SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static LRESULT MCIWND_Command(MCIWndInfo *mwi, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case CTL_PLAYSTOP: MCIWND_ToggleState(mwi); break;
|
|
case CTL_MENU:
|
|
case CTL_TRACKBAR:
|
|
default:
|
|
FIXME("support for command %04x not implement yet\n", LOWORD(wParam));
|
|
}
|
|
return 0L;
|
|
}
|
|
|
|
static void MCIWND_notify_media(MCIWndInfo *mwi)
|
|
{
|
|
if (mwi->dwStyle & (MCIWNDF_NOTIFYMEDIAA | MCIWNDF_NOTIFYMEDIAW))
|
|
{
|
|
if (!mwi->lpName)
|
|
{
|
|
static const WCHAR empty_str[1];
|
|
SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)empty_str);
|
|
}
|
|
else
|
|
{
|
|
if (mwi->dwStyle & MCIWNDF_NOTIFYANSI)
|
|
{
|
|
char *ansi_name;
|
|
int len;
|
|
|
|
len = WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, NULL, 0, NULL, NULL);
|
|
ansi_name = HeapAlloc(GetProcessHeap(), 0, len);
|
|
WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, ansi_name, len, NULL, NULL);
|
|
|
|
SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)ansi_name);
|
|
|
|
HeapFree(GetProcessHeap(), 0, ansi_name);
|
|
}
|
|
else
|
|
SendMessageW(mwi->hwndOwner, MCIWNDM_NOTIFYMEDIA, (WPARAM)mwi->hWnd, (LPARAM)mwi->lpName);
|
|
}
|
|
}
|
|
}
|
|
|
|
static MCIERROR mci_generic_command(MCIWndInfo *mwi, UINT cmd)
|
|
{
|
|
MCI_GENERIC_PARMS mci_generic;
|
|
|
|
mci_generic.dwCallback = 0;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, cmd, 0, (DWORD_PTR)&mci_generic);
|
|
|
|
if (mwi->lasterror)
|
|
return mwi->lasterror;
|
|
|
|
MCIWND_notify_mode(mwi);
|
|
MCIWND_UpdateState(mwi);
|
|
return 0;
|
|
}
|
|
|
|
static LRESULT mci_get_devcaps(MCIWndInfo *mwi, UINT cap)
|
|
{
|
|
MCI_GETDEVCAPS_PARMS mci_devcaps;
|
|
|
|
mci_devcaps.dwItem = cap;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
|
|
MCI_GETDEVCAPS_ITEM,
|
|
(DWORD_PTR)&mci_devcaps);
|
|
if (mwi->lasterror)
|
|
return 0;
|
|
|
|
return mci_devcaps.dwReturn;
|
|
}
|
|
|
|
static LRESULT MCIWND_KeyDown(MCIWndInfo *mwi, UINT key)
|
|
{
|
|
TRACE("%p, key %04x\n", mwi->hWnd, key);
|
|
|
|
switch(key)
|
|
{
|
|
case VK_ESCAPE:
|
|
SendMessageW(mwi->hWnd, MCI_STOP, 0, 0);
|
|
return 0;
|
|
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
MCIWndInfo *mwi;
|
|
|
|
TRACE("%p %04x %08x %08lx\n", hWnd, wMsg, wParam, lParam);
|
|
|
|
mwi = (MCIWndInfo*)GetWindowLongW(hWnd, 0);
|
|
if (!mwi && wMsg != WM_CREATE)
|
|
return DefWindowProcW(hWnd, wMsg, wParam, lParam);
|
|
|
|
switch (wMsg)
|
|
{
|
|
case WM_CREATE:
|
|
MCIWND_Create(hWnd, (CREATESTRUCTW *)lParam);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
if (mwi->uTimer)
|
|
KillTimer(hWnd, mwi->uTimer);
|
|
|
|
if (mwi->mci)
|
|
SendMessageW(hWnd, MCI_CLOSE, 0, 0);
|
|
|
|
HeapFree(GetProcessHeap(), 0, mwi);
|
|
|
|
DestroyWindow(GetDlgItem(hWnd, CTL_MENU));
|
|
DestroyWindow(GetDlgItem(hWnd, CTL_PLAYSTOP));
|
|
DestroyWindow(GetDlgItem(hWnd, CTL_TRACKBAR));
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
{
|
|
MCI_DGV_UPDATE_PARMS mci_update;
|
|
PAINTSTRUCT ps;
|
|
|
|
mci_update.hDC = (wParam) ? (HDC)wParam : BeginPaint(hWnd, &ps);
|
|
|
|
mciSendCommandW(mwi->mci, MCI_UPDATE,
|
|
MCI_DGV_UPDATE_HDC | MCI_DGV_UPDATE_PAINT,
|
|
(DWORD_PTR)&mci_update);
|
|
|
|
if (!wParam) EndPaint(hWnd, &ps);
|
|
return 1;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
return MCIWND_Command(mwi, wParam, lParam);
|
|
|
|
case WM_KEYDOWN:
|
|
return MCIWND_KeyDown(mwi, wParam);
|
|
|
|
case WM_NCACTIVATE:
|
|
if (mwi->uTimer)
|
|
{
|
|
KillTimer(hWnd, mwi->uTimer);
|
|
mwi->uTimer = SetTimer(hWnd, 1, wParam ? mwi->active_timer : mwi->inactive_timer, NULL);
|
|
}
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
MCIWND_UpdateState(mwi);
|
|
return 0;
|
|
|
|
case WM_SIZE:
|
|
SetWindowPos(GetDlgItem(hWnd, CTL_PLAYSTOP), 0, 0, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
|
|
SetWindowPos(GetDlgItem(hWnd, CTL_MENU), 0, 32, HIWORD(lParam) - 32, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE);
|
|
SetWindowPos(GetDlgItem(hWnd, CTL_TRACKBAR), 0, 64, HIWORD(lParam) - 32, LOWORD(lParam) - 64, 32, SWP_NOACTIVATE);
|
|
|
|
if (!(mwi->dwStyle & MCIWNDF_NOAUTOSIZEMOVIE))
|
|
{
|
|
RECT rc;
|
|
|
|
rc.left = rc.top = 0;
|
|
rc.right = LOWORD(lParam);
|
|
rc.bottom = HIWORD(lParam);
|
|
if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
|
|
rc.bottom -= 32; /* subtract the height of the playbar */
|
|
SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
|
|
}
|
|
MCIWND_notify_size(mwi);
|
|
break;
|
|
|
|
case MM_MCINOTIFY:
|
|
MCIWND_notify_mode(mwi);
|
|
MCIWND_UpdateState(mwi);
|
|
return 0;
|
|
|
|
case MCIWNDM_OPENA:
|
|
{
|
|
UNICODE_STRING nameW;
|
|
TRACE("MCIWNDM_OPENA %s\n", debugstr_a((LPSTR)lParam));
|
|
RtlCreateUnicodeStringFromAsciiz(&nameW, (LPCSTR)lParam);
|
|
lParam = (LPARAM)nameW.Buffer;
|
|
}
|
|
/* fall through */
|
|
case MCIWNDM_OPENW:
|
|
{
|
|
RECT rc;
|
|
HCURSOR hCursor;
|
|
MCI_OPEN_PARMSW mci_open;
|
|
MCI_GETDEVCAPS_PARMS mci_devcaps;
|
|
WCHAR aliasW[64];
|
|
WCHAR drv_name[MAX_PATH];
|
|
static const WCHAR formatW[] = {'%','d',0};
|
|
static const WCHAR mci32W[] = {'m','c','i','3','2',0};
|
|
static const WCHAR system_iniW[] = {'s','y','s','t','e','m','.','i','n','i',0};
|
|
|
|
TRACE("MCIWNDM_OPENW %s\n", debugstr_w((LPWSTR)lParam));
|
|
|
|
if (wParam == MCIWNDOPENF_NEW)
|
|
{
|
|
SendMessageW(hWnd, MCIWNDM_NEWW, 0, lParam);
|
|
goto end_of_mci_open;
|
|
}
|
|
|
|
if (mwi->uTimer)
|
|
{
|
|
KillTimer(hWnd, mwi->uTimer);
|
|
mwi->uTimer = 0;
|
|
}
|
|
|
|
hCursor = LoadCursorW(0, (LPWSTR)IDC_WAIT);
|
|
hCursor = SetCursor(hCursor);
|
|
|
|
mci_open.lpstrElementName = (LPWSTR)lParam;
|
|
wsprintfW(aliasW, formatW, (int)hWnd + 1);
|
|
mci_open.lpstrAlias = aliasW;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_OPEN,
|
|
MCI_OPEN_ELEMENT | MCI_OPEN_ALIAS | MCI_WAIT,
|
|
(DWORD_PTR)&mci_open);
|
|
SetCursor(hCursor);
|
|
|
|
if (mwi->lasterror && !(mwi->dwStyle & MCIWNDF_NOERRORDLG))
|
|
{
|
|
/* FIXME: get the caption from resources */
|
|
static const WCHAR caption[] = {'M','C','I',' ','E','r','r','o','r',0};
|
|
WCHAR error_str[MAXERRORLENGTH];
|
|
|
|
mciGetErrorStringW(mwi->lasterror, error_str, MAXERRORLENGTH);
|
|
MessageBoxW(hWnd, error_str, caption, MB_ICONEXCLAMATION | MB_OK);
|
|
MCIWND_notify_error(mwi);
|
|
goto end_of_mci_open;
|
|
}
|
|
|
|
mwi->mci = mci_open.wDeviceID;
|
|
mwi->alias = (int)hWnd + 1;
|
|
|
|
mwi->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW((LPWSTR)lParam) + 1) * sizeof(WCHAR));
|
|
strcpyW(mwi->lpName, (LPWSTR)lParam);
|
|
|
|
MCIWND_UpdateState(mwi);
|
|
|
|
mci_devcaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
|
|
MCI_GETDEVCAPS_ITEM,
|
|
(DWORD_PTR)&mci_devcaps);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
goto end_of_mci_open;
|
|
}
|
|
|
|
mwi->dev_type = mci_devcaps.dwReturn;
|
|
|
|
drv_name[0] = 0;
|
|
SendMessageW(hWnd, MCIWNDM_GETDEVICEW, 256, (LPARAM)drv_name);
|
|
if (drv_name[0] && GetPrivateProfileStringW(mci32W, drv_name, NULL,
|
|
drv_name, MAX_PATH, system_iniW))
|
|
mwi->hdrv = OpenDriver(drv_name, NULL, 0);
|
|
|
|
if (mwi->dev_type == MCI_DEVTYPE_DIGITAL_VIDEO)
|
|
{
|
|
MCI_DGV_WINDOW_PARMSW mci_window;
|
|
|
|
mci_window.hWnd = hWnd;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WINDOW,
|
|
MCI_DGV_WINDOW_HWND,
|
|
(DWORD_PTR)&mci_window);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
goto end_of_mci_open;
|
|
}
|
|
}
|
|
|
|
if (SendMessageW(hWnd, MCIWNDM_GET_DEST, 0, (LPARAM)&rc) == 0)
|
|
{
|
|
mwi->size.cx = rc.right - rc.left;
|
|
mwi->size.cy = rc.bottom - rc.top;
|
|
|
|
rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
|
|
rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
|
|
SendMessageW(hWnd, MCIWNDM_PUT_DEST, 0, (LPARAM)&rc);
|
|
}
|
|
else
|
|
{
|
|
GetClientRect(hWnd, &rc);
|
|
rc.bottom = rc.top;
|
|
}
|
|
|
|
if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
|
|
rc.bottom += 32; /* add the height of the playbar */
|
|
AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
|
|
SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
|
|
rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMIN, 0L, 0L);
|
|
SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
|
|
SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
|
|
mwi->uTimer = SetTimer(hWnd, 1, mwi->active_timer, NULL);
|
|
|
|
MCIWND_notify_media(mwi);
|
|
|
|
end_of_mci_open:
|
|
if (wMsg == MCIWNDM_OPENA)
|
|
HeapFree(GetProcessHeap(), 0, (void *)lParam);
|
|
return mwi->lasterror;
|
|
}
|
|
|
|
case MCIWNDM_GETDEVICEID:
|
|
TRACE("MCIWNDM_GETDEVICEID\n");
|
|
return mwi->mci;
|
|
|
|
case MCIWNDM_GETALIAS:
|
|
TRACE("MCIWNDM_GETALIAS\n");
|
|
return mwi->alias;
|
|
|
|
case MCIWNDM_GET_SOURCE:
|
|
{
|
|
MCI_DGV_RECT_PARMS mci_rect;
|
|
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
|
|
MCI_DGV_WHERE_SOURCE,
|
|
(DWORD_PTR)&mci_rect);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
return mwi->lasterror;
|
|
}
|
|
*(RECT *)lParam = mci_rect.rc;
|
|
TRACE("MCIWNDM_GET_SOURCE: %s\n", wine_dbgstr_rect(&mci_rect.rc));
|
|
return 0;
|
|
}
|
|
|
|
case MCIWNDM_GET_DEST:
|
|
{
|
|
MCI_DGV_RECT_PARMS mci_rect;
|
|
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_WHERE,
|
|
MCI_DGV_WHERE_DESTINATION,
|
|
(DWORD_PTR)&mci_rect);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
return mwi->lasterror;
|
|
}
|
|
*(RECT *)lParam = mci_rect.rc;
|
|
TRACE("MCIWNDM_GET_DEST: %s\n", wine_dbgstr_rect(&mci_rect.rc));
|
|
return 0;
|
|
}
|
|
|
|
case MCIWNDM_PUT_SOURCE:
|
|
{
|
|
MCI_DGV_PUT_PARMS mci_put;
|
|
|
|
mci_put.rc = *(RECT *)lParam;
|
|
TRACE("MCIWNDM_PUT_SOURCE: %s\n", wine_dbgstr_rect(&mci_put.rc));
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
|
|
MCI_DGV_PUT_SOURCE,
|
|
(DWORD_PTR)&mci_put);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
return mwi->lasterror;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
case MCIWNDM_PUT_DEST:
|
|
{
|
|
MCI_DGV_PUT_PARMS mci_put;
|
|
|
|
mci_put.rc = *(RECT *)lParam;
|
|
TRACE("MCIWNDM_PUT_DEST: %s\n", wine_dbgstr_rect(&mci_put.rc));
|
|
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
|
|
MCI_DGV_PUT_DESTINATION | MCI_DGV_RECT,
|
|
(DWORD_PTR)&mci_put);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
return mwi->lasterror;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
case MCIWNDM_GETLENGTH:
|
|
{
|
|
MCI_STATUS_PARMS mci_status;
|
|
|
|
mci_status.dwItem = MCI_STATUS_LENGTH;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
|
|
MCI_STATUS_ITEM,
|
|
(DWORD_PTR)&mci_status);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
return 0;
|
|
}
|
|
TRACE("MCIWNDM_GETLENGTH: %d\n", mci_status.dwReturn);
|
|
return mci_status.dwReturn;
|
|
}
|
|
|
|
case MCIWNDM_GETSTART:
|
|
{
|
|
MCI_STATUS_PARMS mci_status;
|
|
|
|
mci_status.dwItem = MCI_STATUS_POSITION;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
|
|
MCI_STATUS_ITEM | MCI_STATUS_START,
|
|
(DWORD_PTR)&mci_status);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
return 0;
|
|
}
|
|
TRACE("MCIWNDM_GETSTART: %d\n", mci_status.dwReturn);
|
|
return mci_status.dwReturn;
|
|
}
|
|
|
|
case MCIWNDM_GETEND:
|
|
{
|
|
LRESULT start, length;
|
|
|
|
start = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
|
|
length = SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
|
|
TRACE("MCIWNDM_GETEND: %ld\n", start + length);
|
|
return (start + length);
|
|
}
|
|
|
|
case MCIWNDM_GETPOSITIONA:
|
|
case MCIWNDM_GETPOSITIONW:
|
|
{
|
|
MCI_STATUS_PARMS mci_status;
|
|
|
|
TRACE("MCIWNDM_GETPOSITION\n");
|
|
|
|
/* get position string if requested */
|
|
if (wParam && lParam)
|
|
{
|
|
if (wMsg == MCIWNDM_GETPOSITIONA)
|
|
{
|
|
char cmd[64];
|
|
|
|
wsprintfA(cmd, "status %d position", mwi->alias);
|
|
mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
|
|
}
|
|
else
|
|
{
|
|
|
|
WCHAR cmdW[64];
|
|
static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','p','o','s','i','t','i','o','n',0};
|
|
|
|
wsprintfW(cmdW, formatW, mwi->alias);
|
|
mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
|
|
}
|
|
|
|
if (mwi->lasterror)
|
|
return 0;
|
|
}
|
|
|
|
mci_status.dwItem = MCI_STATUS_POSITION;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
|
|
MCI_STATUS_ITEM,
|
|
(DWORD_PTR)&mci_status);
|
|
if (mwi->lasterror)
|
|
return 0;
|
|
|
|
return mci_status.dwReturn;
|
|
}
|
|
|
|
case MCIWNDM_GETMODEA:
|
|
case MCIWNDM_GETMODEW:
|
|
{
|
|
MCI_STATUS_PARMS mci_status;
|
|
|
|
TRACE("MCIWNDM_GETMODE\n");
|
|
|
|
if (!mwi->mci)
|
|
return MCI_MODE_NOT_READY;
|
|
|
|
/* get mode string if requested */
|
|
if (wParam && lParam)
|
|
{
|
|
if (wMsg == MCIWNDM_GETMODEA)
|
|
{
|
|
char cmd[64];
|
|
|
|
wsprintfA(cmd, "status %d mode", mwi->alias);
|
|
mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
|
|
}
|
|
else
|
|
{
|
|
|
|
WCHAR cmdW[64];
|
|
static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','m','o','d','e',0};
|
|
|
|
wsprintfW(cmdW, formatW, mwi->alias);
|
|
mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
|
|
}
|
|
|
|
if (mwi->lasterror)
|
|
return MCI_MODE_NOT_READY;
|
|
}
|
|
|
|
mci_status.dwItem = MCI_STATUS_MODE;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
|
|
MCI_STATUS_ITEM,
|
|
(DWORD_PTR)&mci_status);
|
|
if (mwi->lasterror)
|
|
return MCI_MODE_NOT_READY;
|
|
|
|
return mci_status.dwReturn;
|
|
}
|
|
|
|
case MCIWNDM_PLAYFROM:
|
|
{
|
|
MCI_PLAY_PARMS mci_play;
|
|
|
|
TRACE("MCIWNDM_PLAYFROM %08lx\n", lParam);
|
|
|
|
mci_play.dwCallback = (DWORD_PTR)hWnd;
|
|
mci_play.dwFrom = lParam;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
|
|
MCI_FROM | MCI_NOTIFY,
|
|
(DWORD_PTR)&mci_play);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
return mwi->lasterror;
|
|
}
|
|
|
|
MCIWND_notify_mode(mwi);
|
|
MCIWND_UpdateState(mwi);
|
|
return 0;
|
|
}
|
|
|
|
case MCIWNDM_PLAYTO:
|
|
{
|
|
MCI_PLAY_PARMS mci_play;
|
|
|
|
TRACE("MCIWNDM_PLAYTO %08lx\n", lParam);
|
|
|
|
mci_play.dwCallback = (DWORD_PTR)hWnd;
|
|
mci_play.dwTo = lParam;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
|
|
MCI_TO | MCI_NOTIFY,
|
|
(DWORD_PTR)&mci_play);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
return mwi->lasterror;
|
|
}
|
|
|
|
MCIWND_notify_mode(mwi);
|
|
MCIWND_UpdateState(mwi);
|
|
return 0;
|
|
}
|
|
|
|
case MCIWNDM_PLAYREVERSE:
|
|
{
|
|
MCI_PLAY_PARMS mci_play;
|
|
DWORD flags = MCI_NOTIFY;
|
|
|
|
TRACE("MCIWNDM_PLAYREVERSE %08lx\n", lParam);
|
|
|
|
mci_play.dwCallback = (DWORD_PTR)hWnd;
|
|
mci_play.dwFrom = lParam;
|
|
switch (mwi->dev_type)
|
|
{
|
|
default:
|
|
case MCI_DEVTYPE_ANIMATION:
|
|
flags |= MCI_ANIM_PLAY_REVERSE;
|
|
break;
|
|
|
|
case MCI_DEVTYPE_DIGITAL_VIDEO:
|
|
flags |= MCI_DGV_PLAY_REVERSE;
|
|
break;
|
|
|
|
#ifdef MCI_VCR_PLAY_REVERSE
|
|
case MCI_DEVTYPE_VCR:
|
|
flags |= MCI_VCR_PLAY_REVERSE;
|
|
break;
|
|
#endif
|
|
|
|
case MCI_DEVTYPE_VIDEODISC:
|
|
flags |= MCI_VD_PLAY_REVERSE;
|
|
break;
|
|
|
|
}
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PLAY,
|
|
flags, (DWORD_PTR)&mci_play);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
return mwi->lasterror;
|
|
}
|
|
|
|
MCIWND_notify_mode(mwi);
|
|
MCIWND_UpdateState(mwi);
|
|
return 0;
|
|
}
|
|
|
|
case MCIWNDM_GETERRORA:
|
|
mciGetErrorStringA(mwi->lasterror, (LPSTR)lParam, wParam);
|
|
TRACE("MCIWNDM_GETERRORA: %s\n", debugstr_an((LPSTR)lParam, wParam));
|
|
return mwi->lasterror;
|
|
|
|
case MCIWNDM_GETERRORW:
|
|
mciGetErrorStringW(mwi->lasterror, (LPWSTR)lParam, wParam);
|
|
TRACE("MCIWNDM_GETERRORW: %s\n", debugstr_wn((LPWSTR)lParam, wParam));
|
|
return mwi->lasterror;
|
|
|
|
case MCIWNDM_SETOWNER:
|
|
TRACE("MCIWNDM_SETOWNER %p\n", (HWND)wParam);
|
|
mwi->hwndOwner = (HWND)wParam;
|
|
return 0;
|
|
|
|
case MCIWNDM_SENDSTRINGA:
|
|
{
|
|
UNICODE_STRING stringW;
|
|
|
|
TRACE("MCIWNDM_SENDSTRINGA %s\n", debugstr_a((LPCSTR)lParam));
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
|
|
lParam = (LPARAM)stringW.Buffer;
|
|
}
|
|
/* fall through */
|
|
case MCIWNDM_SENDSTRINGW:
|
|
{
|
|
WCHAR *cmdW, *p;
|
|
|
|
TRACE("MCIWNDM_SENDSTRINGW %s\n", debugstr_w((LPCWSTR)lParam));
|
|
|
|
p = strchrW((LPCWSTR)lParam, ' ');
|
|
if (p)
|
|
{
|
|
static const WCHAR formatW[] = {'%','d',' ',0};
|
|
int len, pos;
|
|
|
|
pos = p - (WCHAR *)lParam + 1;
|
|
len = lstrlenW((LPCWSTR)lParam) + 64;
|
|
|
|
cmdW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
|
|
|
memcpy(cmdW, (void *)lParam, pos * sizeof(WCHAR));
|
|
wsprintfW(cmdW + pos, formatW, mwi->alias);
|
|
strcatW(cmdW, (WCHAR *)lParam + pos);
|
|
}
|
|
else
|
|
cmdW = (LPWSTR)lParam;
|
|
|
|
mwi->lasterror = mciSendStringW(cmdW, mwi->return_string,
|
|
sizeof(mwi->return_string)/sizeof(mwi->return_string[0]),
|
|
0);
|
|
if (mwi->lasterror)
|
|
MCIWND_notify_error(mwi);
|
|
|
|
if (cmdW != (LPWSTR)lParam)
|
|
HeapFree(GetProcessHeap(), 0, cmdW);
|
|
|
|
if (wMsg == MCIWNDM_SENDSTRINGA)
|
|
HeapFree(GetProcessHeap(), 0, (void *)lParam);
|
|
|
|
MCIWND_UpdateState(mwi);
|
|
return mwi->lasterror;
|
|
}
|
|
|
|
case MCIWNDM_RETURNSTRINGA:
|
|
WideCharToMultiByte(CP_ACP, 0, mwi->return_string, -1, (LPSTR)lParam, wParam, NULL, NULL);
|
|
TRACE("MCIWNDM_RETURNTRINGA %s\n", debugstr_an((LPSTR)lParam, wParam));
|
|
return mwi->lasterror;
|
|
|
|
case MCIWNDM_RETURNSTRINGW:
|
|
lstrcpynW((LPWSTR)lParam, mwi->return_string, wParam);
|
|
TRACE("MCIWNDM_RETURNTRINGW %s\n", debugstr_wn((LPWSTR)lParam, wParam));
|
|
return mwi->lasterror;
|
|
|
|
case MCIWNDM_SETTIMERS:
|
|
TRACE("MCIWNDM_SETTIMERS active %d ms, inactive %d ms\n", (int)wParam, (int)lParam);
|
|
mwi->active_timer = (WORD)wParam;
|
|
mwi->inactive_timer = (WORD)lParam;
|
|
return 0;
|
|
|
|
case MCIWNDM_SETACTIVETIMER:
|
|
TRACE("MCIWNDM_SETACTIVETIMER %d ms\n", (int)wParam);
|
|
mwi->active_timer = (WORD)wParam;
|
|
return 0;
|
|
|
|
case MCIWNDM_SETINACTIVETIMER:
|
|
TRACE("MCIWNDM_SETINACTIVETIMER %d ms\n", (int)wParam);
|
|
mwi->inactive_timer = (WORD)wParam;
|
|
return 0;
|
|
|
|
case MCIWNDM_GETACTIVETIMER:
|
|
TRACE("MCIWNDM_GETACTIVETIMER: %d ms\n", mwi->active_timer);
|
|
return mwi->active_timer;
|
|
|
|
case MCIWNDM_GETINACTIVETIMER:
|
|
TRACE("MCIWNDM_GETINACTIVETIMER: %d ms\n", mwi->inactive_timer);
|
|
return mwi->inactive_timer;
|
|
|
|
case MCIWNDM_CHANGESTYLES:
|
|
TRACE("MCIWNDM_CHANGESTYLES mask %08x, set %08lx\n", wParam, lParam);
|
|
/* FIXME: update the visual window state as well:
|
|
* add/remove trackbar, autosize, etc.
|
|
*/
|
|
mwi->dwStyle &= ~wParam;
|
|
mwi->dwStyle |= lParam & wParam;
|
|
return 0;
|
|
|
|
case MCIWNDM_GETSTYLES:
|
|
TRACE("MCIWNDM_GETSTYLES: %08x\n", mwi->dwStyle & 0xffff);
|
|
return mwi->dwStyle & 0xffff;
|
|
|
|
case MCIWNDM_GETDEVICEA:
|
|
{
|
|
MCI_SYSINFO_PARMSA mci_sysinfo;
|
|
|
|
mci_sysinfo.lpstrReturn = (LPSTR)lParam;
|
|
mci_sysinfo.dwRetSize = wParam;
|
|
mwi->lasterror = mciSendCommandA(mwi->mci, MCI_SYSINFO,
|
|
MCI_SYSINFO_INSTALLNAME,
|
|
(DWORD_PTR)&mci_sysinfo);
|
|
TRACE("MCIWNDM_GETDEVICEA: %s\n", debugstr_an((LPSTR)lParam, wParam));
|
|
return 0;
|
|
}
|
|
|
|
case MCIWNDM_GETDEVICEW:
|
|
{
|
|
MCI_SYSINFO_PARMSW mci_sysinfo;
|
|
|
|
mci_sysinfo.lpstrReturn = (LPWSTR)lParam;
|
|
mci_sysinfo.dwRetSize = wParam;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SYSINFO,
|
|
MCI_SYSINFO_INSTALLNAME,
|
|
(DWORD_PTR)&mci_sysinfo);
|
|
TRACE("MCIWNDM_GETDEVICEW: %s\n", debugstr_wn((LPWSTR)lParam, wParam));
|
|
return 0;
|
|
}
|
|
|
|
case MCIWNDM_VALIDATEMEDIA:
|
|
TRACE("MCIWNDM_VALIDATEMEDIA\n");
|
|
if (mwi->mci)
|
|
{
|
|
SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
|
|
SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
|
|
}
|
|
return 0;
|
|
|
|
case MCIWNDM_GETFILENAMEA:
|
|
TRACE("MCIWNDM_GETFILENAMEA: %s\n", debugstr_w(mwi->lpName));
|
|
if (mwi->lpName)
|
|
WideCharToMultiByte(CP_ACP, 0, mwi->lpName, -1, (LPSTR)lParam, wParam, NULL, NULL);
|
|
return 0;
|
|
|
|
case MCIWNDM_GETFILENAMEW:
|
|
TRACE("MCIWNDM_GETFILENAMEW: %s\n", debugstr_w(mwi->lpName));
|
|
if (mwi->lpName)
|
|
lstrcpynW((LPWSTR)lParam, mwi->lpName, wParam);
|
|
return 0;
|
|
|
|
case MCIWNDM_GETTIMEFORMATA:
|
|
case MCIWNDM_GETTIMEFORMATW:
|
|
{
|
|
MCI_STATUS_PARMS mci_status;
|
|
|
|
TRACE("MCIWNDM_GETTIMEFORMAT %08x %08lx\n", wParam, lParam);
|
|
|
|
/* get format string if requested */
|
|
if (wParam && lParam)
|
|
{
|
|
if (wMsg == MCIWNDM_GETTIMEFORMATA)
|
|
{
|
|
char cmd[64];
|
|
|
|
wsprintfA(cmd, "status %d time format", mwi->alias);
|
|
mwi->lasterror = mciSendStringA(cmd, (LPSTR)lParam, wParam, 0);
|
|
if (mwi->lasterror)
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
WCHAR cmdW[64];
|
|
static const WCHAR formatW[] = {'s','t','a','t','u','s',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',0};
|
|
|
|
wsprintfW(cmdW, formatW, mwi->alias);
|
|
mwi->lasterror = mciSendStringW(cmdW, (LPWSTR)lParam, wParam, 0);
|
|
if (mwi->lasterror)
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
mci_status.dwItem = MCI_STATUS_TIME_FORMAT ;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
|
|
MCI_STATUS_ITEM,
|
|
(DWORD_PTR)&mci_status);
|
|
if (mwi->lasterror)
|
|
return 0;
|
|
|
|
return mci_status.dwReturn;
|
|
}
|
|
|
|
case MCIWNDM_SETTIMEFORMATA:
|
|
{
|
|
UNICODE_STRING stringW;
|
|
|
|
TRACE("MCIWNDM_SETTIMEFORMATA %s\n", debugstr_a((LPSTR)lParam));
|
|
|
|
RtlCreateUnicodeStringFromAsciiz(&stringW, (LPCSTR)lParam);
|
|
lParam = (LPARAM)stringW.Buffer;
|
|
}
|
|
/* fall through */
|
|
case MCIWNDM_SETTIMEFORMATW:
|
|
{
|
|
static const WCHAR formatW[] = {'s','e','t',' ','%','d',' ','t','i','m','e',' ','f','o','r','m','a','t',' ',0};
|
|
WCHAR *cmdW;
|
|
|
|
TRACE("MCIWNDM_SETTIMEFORMATW %s\n", debugstr_w((LPWSTR)lParam));
|
|
|
|
if (mwi->mci)
|
|
{
|
|
cmdW = HeapAlloc(GetProcessHeap(), 0, (lstrlenW((LPCWSTR)lParam) + 64) * sizeof(WCHAR));
|
|
wsprintfW(cmdW, formatW, mwi->alias);
|
|
strcatW(cmdW, (WCHAR *)lParam);
|
|
|
|
mwi->lasterror = mciSendStringW(cmdW, NULL, 0, 0);
|
|
|
|
/* fix the range tracking according to the new time format */
|
|
if (!mwi->lasterror)
|
|
SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1,
|
|
SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0));
|
|
}
|
|
|
|
if (wMsg == MCIWNDM_SETTIMEFORMATA)
|
|
HeapFree(GetProcessHeap(), 0, (void *)lParam);
|
|
|
|
return 0;
|
|
}
|
|
|
|
case MCIWNDM_CAN_PLAY:
|
|
TRACE("MCIWNDM_CAN_PLAY\n");
|
|
if (mwi->mci)
|
|
return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_PLAY);
|
|
return 0;
|
|
|
|
case MCIWNDM_CAN_RECORD:
|
|
TRACE("MCIWNDM_CAN_RECORD\n");
|
|
if (mwi->mci)
|
|
return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_RECORD);
|
|
return 0;
|
|
|
|
case MCIWNDM_CAN_SAVE:
|
|
TRACE("MCIWNDM_CAN_SAVE\n");
|
|
if (mwi->mci)
|
|
return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_SAVE);
|
|
return 0;
|
|
|
|
case MCIWNDM_CAN_EJECT:
|
|
TRACE("MCIWNDM_CAN_EJECT\n");
|
|
if (mwi->mci)
|
|
return mci_get_devcaps(mwi, MCI_GETDEVCAPS_CAN_EJECT);
|
|
return 0;
|
|
|
|
case MCIWNDM_CAN_WINDOW:
|
|
TRACE("MCIWNDM_CAN_WINDOW\n");
|
|
switch (mwi->dev_type)
|
|
{
|
|
case MCI_DEVTYPE_ANIMATION:
|
|
case MCI_DEVTYPE_DIGITAL_VIDEO:
|
|
case MCI_DEVTYPE_OVERLAY:
|
|
return 1;
|
|
}
|
|
return 0;
|
|
|
|
case MCIWNDM_CAN_CONFIG:
|
|
TRACE("MCIWNDM_CAN_CONFIG\n");
|
|
if (mwi->hdrv)
|
|
return SendDriverMessage(mwi->hdrv, DRV_QUERYCONFIGURE, 0, 0);
|
|
return 0;
|
|
|
|
case MCIWNDM_SETZOOM:
|
|
TRACE("MCIWNDM_SETZOOM %ld\n", lParam);
|
|
mwi->zoom = lParam;
|
|
|
|
if (mwi->mci && !(mwi->dwStyle & MCIWNDF_NOAUTOSIZEWINDOW))
|
|
{
|
|
RECT rc;
|
|
|
|
rc.left = rc.top = 0;
|
|
rc.right = MulDiv(mwi->size.cx, mwi->zoom, 100);
|
|
rc.bottom = MulDiv(mwi->size.cy, mwi->zoom, 100);
|
|
|
|
if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
|
|
rc.bottom += 32; /* add the height of the playbar */
|
|
AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
|
|
SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
|
|
SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
return 0;
|
|
|
|
case MCIWNDM_GETZOOM:
|
|
TRACE("MCIWNDM_GETZOOM: %d\n", mwi->zoom);
|
|
return mwi->zoom;
|
|
|
|
case MCIWNDM_EJECT:
|
|
{
|
|
MCI_SET_PARMS mci_set;
|
|
|
|
TRACE("MCIWNDM_EJECT\n");
|
|
|
|
mci_set.dwCallback = (DWORD_PTR)hWnd;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SET,
|
|
MCI_SET_DOOR_OPEN | MCI_NOTIFY,
|
|
(DWORD_PTR)&mci_set);
|
|
MCIWND_notify_mode(mwi);
|
|
MCIWND_UpdateState(mwi);
|
|
return mwi->lasterror;
|
|
}
|
|
|
|
case MCIWNDM_SETVOLUME:
|
|
case MCIWNDM_GETVOLUME:
|
|
case MCIWNDM_SETSPEED:
|
|
case MCIWNDM_GETSPEED:
|
|
case MCIWNDM_SETREPEAT:
|
|
case MCIWNDM_GETREPEAT:
|
|
case MCIWNDM_REALIZE:
|
|
case MCIWNDM_GETPALETTE:
|
|
case MCIWNDM_SETPALETTE:
|
|
case MCIWNDM_NEWA:
|
|
case MCIWNDM_NEWW:
|
|
case MCIWNDM_PALETTEKICK:
|
|
case MCIWNDM_OPENINTERFACE:
|
|
FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
|
|
return 0;
|
|
|
|
case MCI_PLAY:
|
|
{
|
|
LRESULT end = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
|
|
return SendMessageW(hWnd, MCIWNDM_PLAYTO, 0, end);
|
|
}
|
|
|
|
case MCI_SEEK:
|
|
{
|
|
MCI_SEEK_PARMS mci_seek;
|
|
|
|
switch (lParam)
|
|
{
|
|
case MCIWND_START:
|
|
lParam = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
|
|
break;
|
|
|
|
case MCIWND_END:
|
|
lParam = SendMessageW(hWnd, MCIWNDM_GETEND, 0, 0);
|
|
break;
|
|
}
|
|
|
|
mci_seek.dwTo = lParam;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_SEEK,
|
|
MCI_TO, (DWORD_PTR)&mci_seek);
|
|
if (mwi->lasterror)
|
|
{
|
|
MCIWND_notify_error(mwi);
|
|
return mwi->lasterror;
|
|
}
|
|
/* update window to reflect the state */
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
return 0;
|
|
}
|
|
|
|
case MCI_CLOSE:
|
|
{
|
|
RECT rc;
|
|
MCI_GENERIC_PARMS mci_generic;
|
|
|
|
if (mwi->hdrv)
|
|
{
|
|
CloseDriver(mwi->hdrv, 0, 0);
|
|
mwi->hdrv = 0;
|
|
}
|
|
|
|
if (mwi->mci)
|
|
{
|
|
mci_generic.dwCallback = 0;
|
|
mwi->lasterror = mciSendCommandW(mwi->mci, MCI_CLOSE,
|
|
0, (DWORD_PTR)&mci_generic);
|
|
mwi->mci = 0;
|
|
}
|
|
|
|
mwi->mode = MCI_MODE_NOT_READY;
|
|
mwi->position = -1;
|
|
|
|
HeapFree(GetProcessHeap(), 0, mwi->lpName);
|
|
mwi->lpName = NULL;
|
|
MCIWND_UpdateState(mwi);
|
|
|
|
GetClientRect(hWnd, &rc);
|
|
rc.bottom = rc.top;
|
|
if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
|
|
rc.bottom += 32; /* add the height of the playbar */
|
|
AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
|
|
SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
|
|
rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
MCIWND_notify_media(mwi);
|
|
return 0;
|
|
}
|
|
|
|
case MCI_PAUSE:
|
|
case MCI_STEP:
|
|
case MCI_STOP:
|
|
case MCI_RESUME:
|
|
mci_generic_command(mwi, wMsg);
|
|
if (wMsg == MCI_STEP && !mwi->lasterror)
|
|
{
|
|
/* update window to reflect the state */
|
|
InvalidateRect(hWnd, NULL, TRUE);
|
|
}
|
|
return mwi->lasterror;
|
|
|
|
case MCI_CONFIGURE:
|
|
if (mwi->hdrv)
|
|
SendDriverMessage(mwi->hdrv, DRV_CONFIGURE, (LPARAM)hWnd, 0);
|
|
return 0;
|
|
|
|
case MCI_BREAK:
|
|
case MCI_CAPTURE:
|
|
case MCI_COPY:
|
|
case MCI_CUE:
|
|
case MCI_CUT:
|
|
case MCI_DELETE:
|
|
case MCI_ESCAPE:
|
|
case MCI_FREEZE:
|
|
case MCI_GETDEVCAPS:
|
|
/*case MCI_INDEX:*/
|
|
case MCI_INFO:
|
|
case MCI_LIST:
|
|
case MCI_LOAD:
|
|
/*case MCI_MARK:*/
|
|
case MCI_MONITOR:
|
|
case MCI_OPEN:
|
|
case MCI_PASTE:
|
|
case MCI_PUT:
|
|
case MCI_QUALITY:
|
|
case MCI_REALIZE:
|
|
case MCI_RECORD:
|
|
case MCI_RESERVE:
|
|
case MCI_RESTORE:
|
|
case MCI_SAVE:
|
|
case MCI_SET:
|
|
case MCI_SETAUDIO:
|
|
/*case MCI_SETTIMECODE:*/
|
|
/*case MCI_SETTUNER:*/
|
|
case MCI_SETVIDEO:
|
|
case MCI_SIGNAL:
|
|
case MCI_SPIN:
|
|
case MCI_STATUS:
|
|
case MCI_SYSINFO:
|
|
case MCI_UNDO:
|
|
case MCI_UNFREEZE:
|
|
case MCI_UPDATE:
|
|
case MCI_WHERE:
|
|
case MCI_WINDOW:
|
|
FIXME("support for MCI_ command %04x not implemented\n", wMsg);
|
|
return 0;
|
|
}
|
|
|
|
if (wMsg >= WM_USER)
|
|
{
|
|
FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
|
|
return 0;
|
|
}
|
|
|
|
if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
|
|
return DefMDIChildProcW(hWnd, wMsg, wParam, lParam);
|
|
|
|
return DefWindowProcW(hWnd, wMsg, wParam, lParam);
|
|
}
|