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@xxxxxxxxxxxxxxx> 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