Implement support for many MCIWndClass MCI_ and MCIWNDM_ messages

Dmitry Timoshkov dmitry at baikal.ru
Mon Dec 15 02:12:40 CST 2003


Hello Alexandre,

I hope you will commit this patch before you go to the vacation.

Sorry, I had to reformat the whole dlls/msvideo/mciwnd.c from
3 spaces indents to a more convenient (for me) 4 spaces.

This patch makes the MCIWnd implementation quite useful for
some not trivial applications.

What remains to be done is a proper support for MCI_WINDOW
command in mciavi.drv.

Changelog:
    Dmitry Timoshkov <dmitry at codeweavers.com>
    Implement support for many MCIWndClass MCI_ and MCIWNDM_ messages.
    Convert MCIWndClass implementation to unicode.

diff -u cvs/hq/wine/dlls/msvideo/Makefile.in wine/dlls/msvideo/Makefile.in
--- cvs/hq/wine/dlls/msvideo/Makefile.in	2003-10-13 21:03:02.000000000 +0900
+++ wine/dlls/msvideo/Makefile.in	2003-12-15 15:39:23.000000000 +0800
@@ -5,6 +5,7 @@ VPATH     = @srcdir@
 MODULE    = msvfw32.dll
 IMPORTS   = winmm comctl32 version user32 gdi32 kernel32
 ALTNAMES  = msvideo.dll
+EXTRALIBS = $(LIBUNICODE)
 
 SPEC_SRCS16 = $(ALTNAMES:.dll=.spec)
 
diff -u cvs/hq/wine/dlls/msvideo/mciwnd.c wine/dlls/msvideo/mciwnd.c
--- cvs/hq/wine/dlls/msvideo/mciwnd.c	2003-12-13 16:27:57.000000000 +0800
+++ wine/dlls/msvideo/mciwnd.c	2003-12-15 15:41:24.000000000 +0800
@@ -1,6 +1,6 @@
 /*
  * 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
@@ -15,6 +15,10 @@
  * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * FIXME:
+ * Add support for all remaining MCI_ and MCIWNDM_ messages.
+ * Add support for MCIWNDF_NOTIFYMODE (all cases), MCIWNDF_NOTIFYPOS.
  */
 
 #define COM_NO_WINDOWS_H
@@ -27,340 +31,688 @@
 #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);
 
-typedef struct {
-   DWORD	dwStyle;
-   MCIDEVICEID	mci;
-   LPSTR	lpName;
-   HWND		hWnd;
-   UINT		uTimer;
+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;
+    UINT        dev_type;
+    LPWSTR      lpName;
+    HWND        hWnd, hwndOwner;
+    UINT        uTimer;
+    MCIERROR    lasterror;
 } MCIWndInfo;
 
-static LRESULT WINAPI	MCIWndProc(HWND hWnd, UINT wMsg, WPARAM lParam1, LPARAM lParam2);
+#define MCIWND_NOTIFY_MODE(info) \
+    if ((info)->dwStyle & MCIWNDF_NOTIFYMODE) \
+        SendMessageW((info)->hwndOwner, MCIWNDM_NOTIFYMODE, (WPARAM)(info)->hWnd, (LPARAM)SendMessageW((info)->hWnd, MCIWNDM_GETMODEW, 0, 0))
 
-#define CTL_PLAYSTOP	0x3200
-#define CTL_MENU	0x3201
-#define CTL_TRACKBAR	0x3202
+#define MCIWND_NOTIFY_SIZE(info) \
+    if (mwi->dwStyle & MCIWNDF_NOTIFYSIZE) \
+        SendMessageW((info)->hwndOwner, MCIWNDM_NOTIFYSIZE, (WPARAM)(info)->hWnd, 0);
 
-/***********************************************************************
- *		MCIWndRegisterClass		[MSVFW32.@]
- */
-BOOL WINAPI MCIWndRegisterClass(HINSTANCE hInst)
-{
-   WNDCLASSA		wc;
+#define MCIWND_NOTIFY_ERROR(info) \
+    if ((info)->dwStyle & MCIWNDF_NOTIFYERROR) \
+        SendMessageW((info)->hwndOwner, MCIWNDM_NOTIFYERROR, (WPARAM)(info)->hWnd, (LPARAM)(info)->lasterror)
 
-   wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC;
-   wc.lpfnWndProc = MCIWndProc;
-   wc.cbClsExtra = 0;
-   wc.cbWndExtra = sizeof(MCIWndInfo*);
-   wc.hInstance = hInst;
-   wc.hIcon = 0;
-   wc.hCursor = LoadCursorW(0, MAKEINTRESOURCEW(IDC_ARROW));
-   wc.hbrBackground = 0;
-   wc.lpszMenuName = NULL;
-   wc.lpszClassName = "MCIWndClass";
+#define MCIWND_NOTIFY_MEDIA(info) MCIWND_notify_media(info)
 
-   return RegisterClassA(&wc);
-}
+static LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
+
+#define CTL_PLAYSTOP    0x3200
+#define CTL_MENU        0x3201
+#define CTL_TRACKBAR    0x3202
 
 /***********************************************************************
- *		MCIWndCreate		[MSVFW32.@]
- *		MCIWndCreateA		[MSVFW32.@]
+ *                MCIWndRegisterClass                [MSVFW32.@]
+ *
+ * NOTE: Native always uses its own hInstance
  */
-HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance,
-			   DWORD dwStyle, LPCSTR szFile)
+BOOL VFWAPIV MCIWndRegisterClass(HINSTANCE hInst)
 {
-   DWORD	wndStyle;
-   MCIWndInfo*	mwi;
-
-   TRACE("%p %p %lx %s\n", hwndParent, hInstance, dwStyle, szFile);
-
-   MCIWndRegisterClass(hInstance);
+    WNDCLASSW wc;
 
-   mwi = HeapAlloc(GetProcessHeap(), 0, sizeof(*mwi));
-   if (!mwi) return 0;
+    wc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC;
+    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;
 
-   mwi->dwStyle = dwStyle;
-   if (szFile)
-     mwi->lpName = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(szFile) + 1), szFile);
-   else
-     mwi->lpName = NULL;
-   mwi->uTimer = 0;
-
-   wndStyle = ((hwndParent) ? (WS_CHILD|WS_BORDER) : WS_OVERLAPPEDWINDOW) |
-              WS_VISIBLE | (dwStyle & 0xFFFF0000);
-
-   if (CreateWindowExA(0, "MCIWndClass", NULL, wndStyle,
-		       CW_USEDEFAULT, CW_USEDEFAULT,
-		       CW_USEDEFAULT, CW_USEDEFAULT,
-		       hwndParent, NULL, hInstance, mwi))
-      return mwi->hWnd;
-
-   if(mwi->lpName) HeapFree(GetProcessHeap(), 0, mwi->lpName);
-   HeapFree(GetProcessHeap(), 0, mwi);
-   return 0;
+    return RegisterClassW(&wc);
 }
 
 /***********************************************************************
- *		MCIWndCreateW				[MSVFW32.@]
+ *                MCIWndCreateW                                [MSVFW32.@]
  */
 HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance,
-			   DWORD dwStyle, LPCWSTR szFile)
-{
-   FIXME("%p %p %lx %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile));
-
-   MCIWndRegisterClass(hInstance);
-
-   return 0;
-}
-
-static DWORD MCIWND_GetStatus(MCIWndInfo* mwi)
+                           DWORD dwStyle, LPCWSTR szFile)
 {
-   MCI_DGV_STATUS_PARMSA	mdsp;
+    TRACE("%p %p %lx %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile));
 
-   memset(&mdsp, 0, sizeof(mdsp));
-   mdsp.dwItem = MCI_STATUS_MODE;
-   if (mciSendCommandA(mwi->mci, MCI_STATUS, MCI_WAIT|MCI_STATUS_ITEM, (DWORD)&mdsp))
-      return MCI_MODE_NOT_READY;
-   if (mdsp.dwReturn == MCI_MODE_STOP && mwi->uTimer) {
-      TRACE("Killing timer\n");
-      KillTimer(mwi->hWnd, 0);
-      mwi->uTimer = 0;
-   }
-   return mdsp.dwReturn;
-}
+    MCIWndRegisterClass(hInstance);
 
-static DWORD MCIWND_Get(MCIWndInfo* mwi, DWORD what)
-{
-   MCI_DGV_STATUS_PARMSA	mdsp;
+    /* window becomes visible after MCI_PLAY command in the case of MCIWNDF_NOOPEN */
+    if (dwStyle & MCIWNDF_NOOPEN)
+        dwStyle &= ~WS_VISIBLE;
 
-   memset(&mdsp, 0, sizeof(mdsp));
-   mdsp.dwItem = what;
-   if (mciSendCommandA(mwi->mci, MCI_STATUS, MCI_WAIT|MCI_STATUS_ITEM, (DWORD)&mdsp))
-      return 0;
-   return mdsp.dwReturn;
+    return CreateWindowExW(0, mciWndClassW, NULL,
+                           dwStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+                           0, 0, 300, 0,
+                           hwndParent, 0, hInstance, (LPVOID)szFile);
 }
 
-static void MCIWND_SetText(MCIWndInfo* mwi)
-{
-   char	buffer[1024];
-
-   if (mwi->dwStyle & MCIWNDF_SHOWNAME) {
-      strcpy(buffer, mwi->lpName);
-   } else {
-      *buffer = 0;
-   }
-
-   if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) {
-      if (*buffer) strcat(buffer, " ");
-      strcat(buffer, "(");
-   }
-
-   if (mwi->dwStyle & MCIWNDF_SHOWPOS) {
-      sprintf(buffer + strlen(buffer), "%ld", MCIWND_Get(mwi, MCI_STATUS_POSITION));
-   }
-
-   if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) {
-      strcat(buffer, " - ");
-   }
-
-   if (mwi->dwStyle & MCIWNDF_SHOWMODE) {
-      switch (MCIWND_GetStatus(mwi)) {
-      case MCI_MODE_NOT_READY: 	strcat(buffer, "not ready");	break;
-      case MCI_MODE_PAUSE:	strcat(buffer, "paused");	break;
-      case MCI_MODE_PLAY:	strcat(buffer, "playing");	break;
-      case MCI_MODE_STOP:	strcat(buffer, "stopped");	break;
-      case MCI_MODE_OPEN:	strcat(buffer, "open");		break;
-      case MCI_MODE_RECORD:	strcat(buffer, "recording");	break;
-      case MCI_MODE_SEEK:	strcat(buffer, "seeking");	break;
-      default:			strcat(buffer, "???");		break;
-      }
-   }
-   if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) {
-      strcat(buffer, " )");
-   }
-   TRACE("=> '%s'\n", buffer);
-   SetWindowTextA(mwi->hWnd, buffer);
-}
-
-static void MCIWND_Create(HWND hWnd, LPCREATESTRUCTA cs)
-{
-   MCI_DGV_OPEN_PARMSA	mdopn;
-   MCI_DGV_RECT_PARMS	mdrct;
-   MMRESULT		mmr;
-   int			cx, cy;
-   HWND			hChld;
-   MCIWndInfo* 		mwi = (MCIWndInfo*)cs->lpCreateParams;
-
-   SetWindowLongA(hWnd, 0, (LPARAM)mwi);
-   mwi->hWnd = hWnd;
-
-   /* now open MCI player for AVI file */
-   memset(&mdopn, 0, sizeof(mdopn));
-   mdopn.lpstrElementName = mwi->lpName;
-   mdopn.dwStyle = WS_VISIBLE|WS_CHILD;
-   mdopn.hWndParent = hWnd;
-
-   mmr = mciSendCommandA(0,  MCI_OPEN, MCI_OPEN_ELEMENT|MCI_DGV_OPEN_PARENT|MCI_DGV_OPEN_WS, (LPARAM)&mdopn);
-   if (mmr) {
-      MessageBoxA(GetTopWindow(hWnd), "Cannot open file", "MciWnd", MB_OK);
-      return;
-   }
-   mwi->mci = mdopn.wDeviceID;
-
-   /* grab AVI window size */
-   memset(&mdrct, 0, sizeof(mdrct));
-   mmr = mciSendCommandA(mwi->mci,  MCI_WHERE, MCI_DGV_WHERE_DESTINATION, (LPARAM)&mdrct);
-   if (mmr) {
-      WARN("Cannot get window rect\n");
-      return;
-   }
-   cx = mdrct.rc.right - mdrct.rc.left;
-   cy = mdrct.rc.bottom - mdrct.rc.top;
-
-   AdjustWindowRect(&mdrct.rc, GetWindowLongA(hWnd, GWL_STYLE), FALSE);
-   SetWindowPos(hWnd, 0, 0, 0, mdrct.rc.right - mdrct.rc.left,
-		mdrct.rc.bottom - mdrct.rc.top + 32, SWP_NOMOVE|SWP_NOZORDER);
-
-   if (!(mwi->dwStyle & MCIWNDF_NOMENU))
-   {
-       hChld = CreateWindowExA(0, "BUTTON", "Menu", WS_CHILD|WS_VISIBLE, 32, cy, 32, 32,
-			   hWnd, (HMENU)CTL_MENU,
-			   (HINSTANCE)GetWindowLongA(hWnd, GWL_HINSTANCE), 0L);
-       TRACE("Get Button2: %p\n", hChld);
-   }
-
-   if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
-   {
-       INITCOMMONCONTROLSEX init;
-
-       /* adding the other elements: play/stop button, menu button, status */
-       hChld = CreateWindowExA(0, "BUTTON", "Play", WS_CHILD|WS_VISIBLE, 0, cy, 32, 32,
-			   hWnd, (HMENU)CTL_PLAYSTOP,
-			   (HINSTANCE)GetWindowLongA(hWnd, GWL_HINSTANCE), 0L);
-       TRACE("Get Button1: %p\n", hChld);
-
-       init.dwSize = sizeof(init);
-       init.dwICC = ICC_BAR_CLASSES;
-       InitCommonControlsEx(&init);
-
-       hChld = CreateWindowExA(0, TRACKBAR_CLASSA, "", WS_CHILD|WS_VISIBLE, 64, cy, cx - 64, 32,
-			   hWnd, (HMENU)CTL_TRACKBAR,
-			   (HINSTANCE)GetWindowLongA(hWnd, GWL_HINSTANCE), 0L);
-       TRACE("Get status: %p\n", hChld);
-       SendMessageA(hChld, TBM_SETRANGEMIN, 0L, 0L);
-       SendMessageA(hChld, TBM_SETRANGEMAX, 1L, MCIWND_Get(mwi, MCI_STATUS_LENGTH));
-   }
-
-   /* FIXME: no need to set it if child window */
-   if (mwi->dwStyle & MCIWNDF_SHOWNAME)
-       MCIWND_SetText(mwi);
-}
-
-static void MCIWND_Paint(MCIWndInfo* mwi, WPARAM wParam)
+/***********************************************************************
+ *                MCIWndCreate                [MSVFW32.@]
+ *                MCIWndCreateA                [MSVFW32.@]
+ */
+HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance,
+                           DWORD dwStyle, LPCSTR szFile)
 {
-   HDC 		hdc;
-   PAINTSTRUCT	ps;
-
-   hdc = (wParam) ? (HDC)wParam : BeginPaint(mwi->hWnd, &ps);
-   /* something to do ? */
-   if (!wParam) EndPaint(mwi->hWnd, &ps);
-}
+    HWND ret;
+    UNICODE_STRING fileW;
 
-static void MCIWND_ToggleState(MCIWndInfo* mwi)
-{
-   MCI_GENERIC_PARMS	mgp;
-   MCI_DGV_PLAY_PARMS	mdply;
+    if (szFile)
+        RtlCreateUnicodeStringFromAsciiz(&fileW, szFile);
+    else
+        fileW.Buffer = NULL;
+
+    ret = MCIWndCreateW(hwndParent, hInstance, dwStyle, fileW.Buffer);
+
+    RtlFreeUnicodeString(&fileW);
+    return ret;
+}
+
+static void MCIWND_UpdateText(MCIWndInfo *mwi)
+{
+    WCHAR buffer[1024];
+
+    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)
+    {
+        static const WCHAR formatW[] = {'%','l','d',0};
+        sprintfW(buffer + strlenW(buffer), formatW, SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 0, 0));
+    }
+
+    if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE))
+    {
+        static const WCHAR dashW[] = {' ','-',' ',0};
+        strcatW(buffer, dashW);
+    }
+
+    if (mwi->dwStyle & MCIWNDF_SHOWMODE)
+    {
+        /* FIXME: get the status string from resources */
+        static const WCHAR not_readyW[] = {'n','o','t',' ','r','e','a','d','y',0};
+        static const WCHAR pausedW[] = {'p','a','u','s','e','d',0};
+        static const WCHAR playingW[] = {'p','l','a','y','i','n','g',0};
+        static const WCHAR stoppedW[] = {'s','t','o','p','p','e','d',0};
+        static const WCHAR openW[] = {'o','p','e','n',0};
+        static const WCHAR recordingW[] = {'r','e','c','o','r','d','i','n','g',0};
+        static const WCHAR seekingW[] = {'s','e','e','k','i','n','g',0};
+        static const WCHAR unknownW[] = {'?','?','?',0};
+
+        switch (SendMessageW(mwi->hWnd, MCIWNDM_GETMODEW, 0, 0))
+        {
+            case MCI_MODE_NOT_READY: strcatW(buffer, not_readyW); break;
+            case MCI_MODE_PAUSE: strcatW(buffer, pausedW); break;
+            case MCI_MODE_PLAY: strcatW(buffer, playingW); break;
+            case MCI_MODE_STOP: strcatW(buffer, stoppedW); break;
+            case MCI_MODE_OPEN: strcatW(buffer, openW); break;
+            case MCI_MODE_RECORD: strcatW(buffer, recordingW); break;
+            case MCI_MODE_SEEK:        strcatW(buffer, seekingW); break;
+            default: strcatW(buffer, unknownW); break;
+        }
+    }
+
+    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};
+
+    /* This sets the default window size */
+    SendMessageW(hWnd, MCI_CLOSE, 0, 0);
+
+    mwi = HeapAlloc(GetProcessHeap(), 0, sizeof(*mwi));
+    if (!mwi) return -1;
+
+    SetWindowLongW(hWnd, 0, (LPARAM)mwi);
+
+    mwi->dwStyle = cs->style;
+    mwi->mci = 0;
+    mwi->lpName = NULL;
+    mwi->uTimer = 0;
+    mwi->hWnd = hWnd;
+    mwi->hwndOwner = cs->hwndParent;
+    mwi->lasterror = 0;
+
+    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);
+    }
+
+    SendMessageW(hWnd, MCIWNDM_OPENW, 0, (LPARAM)cs->lpCreateParams);
+
+    MCIWND_UpdateText(mwi);
+    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:
+        MessageBoxA(0, "ooch", "NIY", MB_OK);
+    }
+    return 0L;
+}
+
+static void MCIWND_Timer(MCIWndInfo *mwi)
+{
+    LONG pos = SendMessageW(mwi->hWnd, MCIWNDM_GETPOSITIONW, 0, 0);
+    TRACE("%ld\n", pos);
+    SendDlgItemMessageW(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, TRUE, pos);
+    MCIWND_UpdateText(mwi);
+}
+
+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 LRESULT WINAPI MCIWndProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
+{
+    MCIWndInfo *mwi;
+
+    if (wMsg == WM_CREATE)
+        return MCIWND_Create(hWnd, (CREATESTRUCTW *)lParam);
+
+    mwi = (MCIWndInfo*)GetWindowLongW(hWnd, 0);
+    if (!mwi)
+        return DefWindowProcW(hWnd, wMsg, wParam, lParam);
+
+    switch (wMsg)
+    {
+    case WM_DESTROY:
+        if (mwi->uTimer)
+            KillTimer(hWnd, mwi->uTimer);
+
+        SendMessageW(hWnd, MCI_CLOSE, 0, 0);
+
+        if (mwi->lpName)
+            HeapFree(GetProcessHeap(), 0, mwi->lpName);
+        HeapFree(GetProcessHeap(), 0, mwi);
+        return 0;
 
-   memset(&mgp, 0, sizeof(mgp));
-   memset(&mdply, 0, sizeof(mdply));
+    case WM_PAINT:
+        {
+            HDC hdc;
+            PAINTSTRUCT ps;
+
+            hdc = (wParam) ? (HDC)wParam : BeginPaint(mwi->hWnd, &ps);
+            /* something to do ? */
+            if (!wParam) EndPaint(mwi->hWnd, &ps);
+            return 1;
+        }
 
-   switch (MCIWND_GetStatus(mwi)) {
-   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:
-      mciSendCommandA(mwi->mci, MCI_RESUME, MCI_WAIT, (LPARAM)&mgp);
-      break;
-   case MCI_MODE_PLAY:
-      mciSendCommandA(mwi->mci, MCI_PAUSE, MCI_WAIT, (LPARAM)&mgp);
-      break;
-   case MCI_MODE_STOP:
-      mdply.dwFrom = 0L;
-      mciSendCommandA(mwi->mci, MCI_PLAY, MCI_FROM, (LPARAM)&mdply);
-      mwi->uTimer = SetTimer(mwi->hWnd, 0, 333, 0L);
-      TRACE("Timer=%u\n", mwi->uTimer);
-      break;
-   }
-}
+    case WM_COMMAND:
+        return MCIWND_Command(mwi, wParam, lParam);
 
-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:
-      MessageBoxA(0, "ooch", "NIY", MB_OK);
-   }
-   return 0L;
-}
+    case WM_TIMER:
+        MCIWND_Timer(mwi);
+        return 0;
 
-static void MCIWND_Timer(MCIWndInfo* mwi, WPARAM wParam, LPARAM lParam)
-{
-   TRACE("%ld\n", MCIWND_Get(mwi, MCI_STATUS_POSITION));
-   SendDlgItemMessageA(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, 1, MCIWND_Get(mwi, MCI_STATUS_POSITION));
-   MCIWND_SetText(mwi);
-}
+    case WM_SIZE:
+        {
+            MCIWND_NOTIFY_SIZE(mwi);
+
+            if (wParam == SIZE_MINIMIZED) return 0;
+
+            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);
+            return 0;
+        }
 
-static void MCIWND_Close(MCIWndInfo* mwi)
-{
-   MCI_GENERIC_PARMS	mgp;
+    case MM_MCINOTIFY:
+        MCIWND_NOTIFY_MODE(mwi);
+        return 0;
 
-   memset(&mgp, 0, sizeof(mgp));
 
-   mciSendCommandA(mwi->mci, MCI_CLOSE, 0, (LPARAM)&mgp);
-}
+    case MCIWNDM_OPENA:
+        {
+            UNICODE_STRING nameW;
+            RtlCreateUnicodeStringFromAsciiz(&nameW, (LPCSTR)lParam);
+            lParam = (LPARAM)nameW.Buffer;
+        }
+        /* fall through */
+    case MCIWNDM_OPENW:
+        {
+            RECT rc;
+
+            if (mwi->uTimer)
+            {
+                KillTimer(hWnd, mwi->uTimer);
+                mwi->uTimer = 0;
+            }
+
+            if (lParam)
+            {
+                HCURSOR hCursor;
+                MCI_OPEN_PARMSW mci_open;
+                MCI_GETDEVCAPS_PARMS mci_devcaps;
+
+                hCursor = LoadCursorW(0, (LPWSTR)IDC_WAIT);
+                hCursor = SetCursor(hCursor);
+
+                mci_open.lpstrElementName = (LPWSTR)lParam;
+                mwi->lasterror = mciSendCommandW(mwi->mci, MCI_OPEN,
+                                                 MCI_OPEN_ELEMENT | MCI_WAIT,
+                                                 (DWORD_PTR)&mci_open);
+                SetCursor(hCursor);
+
+                if (mwi->lasterror)
+                {
+                    /* 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->lpName = HeapAlloc(GetProcessHeap(), 0, (strlenW((LPWSTR)lParam) + 1) * sizeof(WCHAR));
+                strcpyW(mwi->lpName, (LPWSTR)lParam);
+
+                mci_devcaps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE;
+                mwi->lasterror = mciSendCommandW(mwi->mci, MCI_GETDEVCAPS,
+                                                 MCI_GETDEVCAPS_ITEM,
+                                                (DWORD_PTR)&mci_devcaps);
+                if (mwi->lasterror)
+                {
+                    WCHAR error_str[MAXERRORLENGTH];
+
+                    mciGetErrorStringW(mwi->lasterror, error_str, MAXERRORLENGTH);
+
+                    MCIWND_NOTIFY_ERROR(mwi);
+                    goto end_of_mci_open;
+                }
+
+                mwi->dev_type = mci_devcaps.dwReturn;
+
+                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)
+            {
+                GetClientRect(hWnd, &rc);
+                rc.bottom = rc.top;
+            }
+
+            AdjustWindowRect(&rc, GetWindowLongW(hWnd, GWL_STYLE), FALSE);
+            if (!(mwi->dwStyle & MCIWNDF_NOPLAYBAR))
+                rc.bottom += 32; /* add the height of the playbar */
+            SetWindowPos(hWnd, 0, 0, 0, rc.right - rc.left,
+                rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER);
+
+            if (mwi->dwStyle & MCIWNDF_NOOPEN)
+                ShowWindow(mwi->hWnd, SW_SHOW);
+            MCIWND_NOTIFY_MEDIA(mwi);
+
+            SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMIN, 0L, 0L);
+            SendDlgItemMessageW(hWnd, CTL_TRACKBAR, TBM_SETRANGEMAX, 1L, SendMessageW(mwi->hWnd, MCIWNDM_GETLENGTH, 0, 0));
+            SetTimer(hWnd, 1, 500, NULL);
+
+end_of_mci_open:
+            if (wMsg == MCIWNDM_OPENA)
+                HeapFree(GetProcessHeap(), 0, (void *)lParam);
+            return mwi->lasterror;
+        }
+
+    case MCIWNDM_GETDEVICEID:
+        return mwi->mci;
+
+    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;
+            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;
+            return 0;
+        }
+
+    case MCIWNDM_PUT_SOURCE:
+        {
+            MCI_DGV_PUT_PARMS mci_put;
+
+            mci_put.rc = *(RECT *)lParam;
+            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;
+            mwi->lasterror = mciSendCommandW(mwi->mci, MCI_PUT,
+                                             MCI_DGV_PUT_DESTINATION,
+                                             (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;
+            }
+            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;
+            }
+            return mci_status.dwReturn;
+        }
+
+    case MCIWNDM_GETEND:
+        {
+            LRESULT start, length;
+
+            start = SendMessageW(hWnd, MCIWNDM_GETSTART, 0, 0);
+            length = SendMessageW(hWnd, MCIWNDM_GETLENGTH, 0, 0);
+            return (start + length);
+        }
+
+    case MCIWNDM_GETPOSITIONA:
+    case MCIWNDM_GETPOSITIONW:
+        {
+            MCI_STATUS_PARMS mci_status;
+
+            mci_status.dwItem = MCI_STATUS_POSITION;
+            mwi->lasterror = mciSendCommandW(mwi->mci, MCI_STATUS,
+                                             MCI_STATUS_ITEM,
+                                             (DWORD_PTR)&mci_status);
+            if (mwi->lasterror)
+            {
+                MCIWND_NOTIFY_ERROR(mwi);
+                return 0;
+            }
+            return mci_status.dwReturn;
+        }
+
+    case MCIWNDM_GETMODEA:
+    case MCIWNDM_GETMODEW:
+        {
+            MCI_STATUS_PARMS mci_status;
+
+            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_PLAYTO:
+        {
+            MCI_PLAY_PARMS mci_play;
+
+            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;
+            }
+            return 0;
+        }
+
+    case MCIWNDM_RETURNSTRINGA:
+        mciGetErrorStringA(mwi->lasterror, (LPSTR)lParam, wParam);
+        return mwi->lasterror;
+
+    case MCIWNDM_RETURNSTRINGW:
+        mciGetErrorStringW(mwi->lasterror, (LPWSTR)lParam, wParam);
+        return mwi->lasterror;
 
-static LRESULT WINAPI	MCIWndProc(HWND hWnd, UINT wMsg, WPARAM lParam1, LPARAM lParam2)
-{
-   MCIWndInfo*	mwi = (MCIWndInfo*)GetWindowLongA(hWnd, 0);
+    case MCIWNDM_SETOWNER:
+        mwi->hwndOwner = (HWND)wParam;
+        return 0;
 
-   if (mwi || wMsg == WM_CREATE) {
-      switch (wMsg) {
-      case WM_CREATE:
-	 MCIWND_Create(hWnd, (CREATESTRUCTA*)lParam2);
-	 return 0;
-      case WM_DESTROY:
-	 MCIWND_Close(mwi);
-	 HeapFree(GetProcessHeap(), 0, mwi->lpName);
-	 HeapFree(GetProcessHeap(), 0, mwi);
-	 break;
-      case WM_PAINT:
-	 MCIWND_Paint(mwi, lParam1);
-	 break;
-      case WM_COMMAND:
-	 return MCIWND_Command(mwi, lParam1, lParam2);
-      case WM_TIMER:
-	 MCIWND_Timer(mwi, lParam1, lParam2);
-	 return TRUE;
-      }
-   }
+    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;
+            }
+            return 0;
+        }
+
+    case MCI_CLOSE:
+        if (mwi->mci)
+        {
+            MCI_GENERIC_PARMS mci_generic;
+
+            mci_generic.dwCallback = 0;
+            mciSendCommandW(mwi->mci, MCI_CLOSE, 0, (DWORD_PTR)&mci_generic);
+            mwi->mci = 0;
+        }
+        return 0;
+    }
 
-   if ((wMsg >= WM_USER) && (wMsg < WM_APP))
-   {
+    if ((wMsg >= WM_USER) && (wMsg < WM_APP))
+    {
         FIXME("support for MCIWNDM_ message WM_USER+%d not implemented\n", wMsg - WM_USER);
         return 0;
-   }
+    }
 
-   return DefWindowProcA(hWnd, wMsg, lParam1, lParam2);
+    return DefWindowProcW(hWnd, wMsg, wParam, lParam);
 }
diff -u cvs/hq/wine/dlls/msvideo/msvfw32.spec wine/dlls/msvideo/msvfw32.spec
--- cvs/hq/wine/dlls/msvideo/msvfw32.spec	2003-06-30 16:20:47.000000000 +0900
+++ wine/dlls/msvideo/msvfw32.spec	2003-12-15 15:15:22.000000000 +0800
@@ -47,5 +47,5 @@
 @ cdecl   MCIWndCreate (long long long str) MCIWndCreateA
 @ cdecl   MCIWndCreateA (long long long str)
 @ cdecl   MCIWndCreateW (long long long wstr)
-@ stdcall MCIWndRegisterClass (long)
+@ cdecl   MCIWndRegisterClass (long)
 @ stub    StretchDIB
diff -u cvs/hq/wine/dlls/msvideo/msvideo_main.c wine/dlls/msvideo/msvideo_main.c
--- cvs/hq/wine/dlls/msvideo/msvideo_main.c	2003-09-12 12:52:22.000000000 +0900
+++ wine/dlls/msvideo/msvideo_main.c	2003-12-15 15:16:12.000000000 +0800
@@ -62,6 +62,22 @@ struct _reg_driver
 
 static reg_driver* reg_driver_list = NULL;
 
+HMODULE MSVFW32_hModule;
+
+BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
+{
+    TRACE("%p,%lx,%p\n", hinst, reason, reserved);
+
+    switch(reason)
+    {
+        case DLL_PROCESS_ATTACH:
+            DisableThreadLibraryCalls(hinst);
+            MSVFW32_hModule = (HMODULE)hinst;
+            break;
+    }
+    return TRUE;
+}
+
 static int compare_fourcc(DWORD fcc1, DWORD fcc2)
 {
   char fcc_str1[5];
diff -u cvs/hq/wine/include/vfw.h wine/include/vfw.h
--- cvs/hq/wine/include/vfw.h	2003-11-26 15:16:19.000000000 +0800
+++ wine/include/vfw.h	2003-12-15 15:16:51.000000000 +0800
@@ -1290,8 +1290,10 @@ BOOL WINAPI GetSaveFileNamePreviewW(LPOP
 #define AVIERR_USERABORT	MAKE_AVIERR(198)
 #define AVIERR_ERROR		MAKE_AVIERR(199)
 
-HWND        VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance, DWORD dwStyle, LPCSTR szFile);
-HWND        VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance, DWORD dwStyle, LPCWSTR szFile);
+BOOL VFWAPIV MCIWndRegisterClass(HINSTANCE);
+
+HWND VFWAPIV MCIWndCreateA(HWND, HINSTANCE, DWORD, LPCSTR);
+HWND VFWAPIV MCIWndCreateW(HWND, HINSTANCE, DWORD, LPCWSTR);
 #define     MCIWndCreate WINELIB_NAME_AW(MCIWndCreate)
 
 #define MCIWNDOPENF_NEW			0x0001






More information about the wine-patches mailing list