Added regedit unit test, a couple minor changes to regedit.
[wine] / dlls / msvideo / mciwnd.c
1 /*
2  * Copyright 2000 Eric Pouech
3  *
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22
23 #include "winbase.h"
24 #include "windef.h"
25 #include "winnls.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "vfw.h"
29 #include "wine/mmsystem16.h"
30 #include "digitalv.h"
31 #include "commctrl.h"
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(mci);
35
36 typedef struct {
37    DWORD        dwStyle;
38    MCIDEVICEID  mci;
39    LPSTR        lpName;
40    HWND         hWnd;
41    UINT         uTimer;
42 } MCIWndInfo;
43
44 static LRESULT WINAPI   MCIWndProc(HWND hWnd, UINT wMsg, WPARAM lParam1, LPARAM lParam2);
45
46 #define CTL_PLAYSTOP    0x3200
47 #define CTL_MENU        0x3201
48 #define CTL_TRACKBAR    0x3202
49
50 /***********************************************************************
51  *              MCIWndRegisterClass             [MSVFW32.@]
52  */
53 BOOL WINAPI MCIWndRegisterClass(HINSTANCE hInst)
54 {
55    WNDCLASSA            wc;
56
57    /* since window creation will also require some common controls, init them */
58    InitCommonControls();
59
60    wc.style = 0;
61    wc.lpfnWndProc = MCIWndProc;
62    wc.cbClsExtra = 0;
63    wc.cbWndExtra = sizeof(MCIWndInfo*);
64    wc.hInstance = hInst;
65    wc.hIcon = 0;
66    wc.hCursor = 0;
67    wc.hbrBackground = 0;
68    wc.lpszMenuName = NULL;
69    wc.lpszClassName = "MCIWndClass";
70
71    return RegisterClassA(&wc);
72
73 }
74
75 /***********************************************************************
76  *              MCIWndCreate            [MSVFW32.@]
77  *              MCIWndCreateA           [MSVFW32.@]
78  */
79 HWND VFWAPIV MCIWndCreateA(HWND hwndParent, HINSTANCE hInstance,
80                            DWORD dwStyle, LPCSTR szFile)
81 {
82    DWORD        wndStyle;
83    MCIWndInfo*  mwi;
84
85    TRACE("%x %x %lx %s\n", hwndParent, hInstance, dwStyle, szFile);
86
87    MCIWndRegisterClass(hInstance);
88
89    mwi = HeapAlloc(GetProcessHeap(), 0, sizeof(*mwi));
90    if (!mwi) return 0;
91
92    mwi->dwStyle = dwStyle;
93    if (szFile)
94      mwi->lpName = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(szFile) + 1), szFile);
95    else
96      mwi->lpName = NULL;
97    mwi->uTimer = 0;
98
99    wndStyle = ((hwndParent) ? (WS_CHILD|WS_BORDER) : WS_OVERLAPPEDWINDOW) |
100               WS_VISIBLE | (dwStyle & 0xFFFF0000);
101
102    if (CreateWindowExA(0, "MCIWndClass", NULL, wndStyle,
103                        CW_USEDEFAULT, CW_USEDEFAULT,
104                        CW_USEDEFAULT, CW_USEDEFAULT,
105                        hwndParent, (HMENU)0, hInstance, mwi))
106       return mwi->hWnd;
107
108    if(mwi->lpName) HeapFree(GetProcessHeap(), 0, mwi->lpName);
109    HeapFree(GetProcessHeap(), 0, mwi);
110    return 0;
111 }
112
113 /***********************************************************************
114  *              MCIWndCreateW                           [MSVFW32.@]
115  */
116 HWND VFWAPIV MCIWndCreateW(HWND hwndParent, HINSTANCE hInstance,
117                            DWORD dwStyle, LPCWSTR szFile)
118 {
119    FIXME("%x %x %lx %s\n", hwndParent, hInstance, dwStyle, debugstr_w(szFile));
120
121    MCIWndRegisterClass(hInstance);
122
123    return 0;
124 }
125
126 static DWORD MCIWND_GetStatus(MCIWndInfo* mwi)
127 {
128    MCI_DGV_STATUS_PARMSA        mdsp;
129
130    memset(&mdsp, 0, sizeof(mdsp));
131    mdsp.dwItem = MCI_STATUS_MODE;
132    if (mciSendCommandA(mwi->mci, MCI_STATUS, MCI_WAIT|MCI_STATUS_ITEM, (DWORD)&mdsp))
133       return MCI_MODE_NOT_READY;
134    if (mdsp.dwReturn == MCI_MODE_STOP && mwi->uTimer) {
135       TRACE("Killing timer\n");
136       KillTimer(mwi->hWnd, 0);
137       mwi->uTimer = 0;
138    }
139    return mdsp.dwReturn;
140 }
141
142 static DWORD MCIWND_Get(MCIWndInfo* mwi, DWORD what)
143 {
144    MCI_DGV_STATUS_PARMSA        mdsp;
145
146    memset(&mdsp, 0, sizeof(mdsp));
147    mdsp.dwItem = what;
148    if (mciSendCommandA(mwi->mci, MCI_STATUS, MCI_WAIT|MCI_STATUS_ITEM, (DWORD)&mdsp))
149       return 0;
150    return mdsp.dwReturn;
151 }
152
153 static void MCIWND_SetText(MCIWndInfo* mwi)
154 {
155    char buffer[1024];
156
157    if (mwi->dwStyle & MCIWNDF_SHOWNAME) {
158       strcpy(buffer, mwi->lpName);
159    } else {
160       *buffer = 0;
161    }
162
163    if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) {
164       if (*buffer) strcat(buffer, " ");
165       strcat(buffer, "(");
166    }
167
168    if (mwi->dwStyle & MCIWNDF_SHOWPOS) {
169       sprintf(buffer + strlen(buffer), "%ld", MCIWND_Get(mwi, MCI_STATUS_POSITION));
170    }
171
172    if ((mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) == (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) {
173       strcat(buffer, " - ");
174    }
175
176    if (mwi->dwStyle & MCIWNDF_SHOWMODE) {
177       switch (MCIWND_GetStatus(mwi)) {
178       case MCI_MODE_NOT_READY:  strcat(buffer, "not ready");    break;
179       case MCI_MODE_PAUSE:      strcat(buffer, "paused");       break;
180       case MCI_MODE_PLAY:       strcat(buffer, "playing");      break;
181       case MCI_MODE_STOP:       strcat(buffer, "stopped");      break;
182       case MCI_MODE_OPEN:       strcat(buffer, "open");         break;
183       case MCI_MODE_RECORD:     strcat(buffer, "recording");    break;
184       case MCI_MODE_SEEK:       strcat(buffer, "seeking");      break;
185       default:                  strcat(buffer, "???");          break;
186       }
187    }
188    if (mwi->dwStyle & (MCIWNDF_SHOWPOS|MCIWNDF_SHOWMODE)) {
189       strcat(buffer, " )");
190    }
191    TRACE("=> '%s'\n", buffer);
192    SetWindowTextA(mwi->hWnd, buffer);
193 }
194
195 static void MCIWND_Create(HWND hWnd, LPCREATESTRUCTA cs)
196 {
197    MCI_DGV_OPEN_PARMSA  mdopn;
198    MCI_DGV_RECT_PARMS   mdrct;
199    MMRESULT             mmr;
200    int                  cx, cy;
201    HWND                 hChld;
202    MCIWndInfo*          mwi = (MCIWndInfo*)cs->lpCreateParams;
203
204    SetWindowLongA(hWnd, 0, (LPARAM)mwi);
205    mwi->hWnd = hWnd;
206
207    /* now open MCI player for AVI file */
208    memset(&mdopn, 0, sizeof(mdopn));
209    mdopn.lpstrElementName = mwi->lpName;
210    mdopn.dwStyle = WS_VISIBLE|WS_CHILD;
211    mdopn.hWndParent = hWnd;
212
213    mmr = mciSendCommandA(0,  MCI_OPEN, MCI_OPEN_ELEMENT|MCI_DGV_OPEN_PARENT|MCI_DGV_OPEN_WS, (LPARAM)&mdopn);
214    if (mmr) {
215       MessageBoxA(GetTopWindow(hWnd), "Cannot open file", "MciWnd", MB_OK);
216       return;
217    }
218    mwi->mci = mdopn.wDeviceID;
219
220    /* grab AVI window size */
221    memset(&mdrct, 0, sizeof(mdrct));
222    mmr = mciSendCommandA(mwi->mci,  MCI_WHERE, MCI_DGV_WHERE_DESTINATION, (LPARAM)&mdrct);
223    if (mmr) {
224       WARN("Cannot get window rect\n");
225       return;
226    }
227    cx = mdrct.rc.right - mdrct.rc.left;
228    cy = mdrct.rc.bottom - mdrct.rc.top;
229
230    AdjustWindowRect(&mdrct.rc, GetWindowLongA(hWnd, GWL_STYLE), FALSE);
231    SetWindowPos(hWnd, 0, 0, 0, mdrct.rc.right - mdrct.rc.left,
232                 mdrct.rc.bottom - mdrct.rc.top + 32, SWP_NOMOVE|SWP_NOZORDER);
233
234    /* adding the other elements: play/stop button, menu button, status */
235    hChld = CreateWindowExA(0, "BUTTON", "Play", WS_CHILD|WS_VISIBLE, 0, cy, 32, 32,
236                            hWnd, (HMENU)CTL_PLAYSTOP, GetWindowLongA(hWnd, GWL_HINSTANCE), 0L);
237    TRACE("Get Button1: %04x\n", hChld);
238    hChld = CreateWindowExA(0, "BUTTON", "Menu", WS_CHILD|WS_VISIBLE, 32, cy, 32, 32,
239                            hWnd, (HMENU)CTL_MENU, GetWindowLongA(hWnd, GWL_HINSTANCE), 0L);
240    TRACE("Get Button2: %04x\n", hChld);
241    hChld = CreateWindowExA(0, TRACKBAR_CLASSA, "", WS_CHILD|WS_VISIBLE, 64, cy, cx - 64, 32,
242                            hWnd, (HMENU)CTL_TRACKBAR, GetWindowLongA(hWnd, GWL_HINSTANCE), 0L);
243    TRACE("Get status: %04x\n", hChld);
244    SendMessageA(hChld, TBM_SETRANGEMIN, 0L, 0L);
245    SendMessageA(hChld, TBM_SETRANGEMAX, 1L, MCIWND_Get(mwi, MCI_STATUS_LENGTH));
246
247    /* FIXME: no need to set it if child window */
248    MCIWND_SetText(mwi);
249 }
250
251 static void MCIWND_Paint(MCIWndInfo* mwi, WPARAM wParam)
252 {
253    HDC          hdc;
254    PAINTSTRUCT  ps;
255
256    hdc = (wParam) ? (HDC)wParam : BeginPaint(mwi->hWnd, &ps);
257    /* something to do ? */
258    if (!wParam) EndPaint(mwi->hWnd, &ps);
259 }
260
261 static void MCIWND_ToggleState(MCIWndInfo* mwi)
262 {
263    MCI_GENERIC_PARMS    mgp;
264    MCI_DGV_PLAY_PARMS   mdply;
265
266    memset(&mgp, 0, sizeof(mgp));
267    memset(&mdply, 0, sizeof(mdply));
268
269    switch (MCIWND_GetStatus(mwi)) {
270    case MCI_MODE_NOT_READY:
271    case MCI_MODE_RECORD:
272    case MCI_MODE_SEEK:
273    case MCI_MODE_OPEN:
274       TRACE("Cannot do much...\n");
275       break;
276    case MCI_MODE_PAUSE:
277       mciSendCommandA(mwi->mci, MCI_RESUME, MCI_WAIT, (LPARAM)&mgp);
278       break;
279    case MCI_MODE_PLAY:
280       mciSendCommandA(mwi->mci, MCI_PAUSE, MCI_WAIT, (LPARAM)&mgp);
281       break;
282    case MCI_MODE_STOP:
283       mdply.dwFrom = 0L;
284       mciSendCommandA(mwi->mci, MCI_PLAY, MCI_FROM, (LPARAM)&mdply);
285       mwi->uTimer = SetTimer(mwi->hWnd, 0, 333, 0L);
286       TRACE("Timer=%u\n", mwi->uTimer);
287       break;
288    }
289 }
290
291 static LRESULT MCIWND_Command(MCIWndInfo* mwi, WPARAM wParam, LPARAM lParam)
292 {
293    switch (LOWORD(wParam)) {
294    case CTL_PLAYSTOP:   MCIWND_ToggleState(mwi);        break;
295    case CTL_MENU:
296    case CTL_TRACKBAR:
297    default:
298       MessageBoxA(0, "ooch", "NIY", MB_OK);
299    }
300    return 0L;
301 }
302
303 static void MCIWND_Timer(MCIWndInfo* mwi, WPARAM wParam, LPARAM lParam)
304 {
305    TRACE("%ld\n", MCIWND_Get(mwi, MCI_STATUS_POSITION));
306    SendDlgItemMessageA(mwi->hWnd, CTL_TRACKBAR, TBM_SETPOS, 1, MCIWND_Get(mwi, MCI_STATUS_POSITION));
307    MCIWND_SetText(mwi);
308 }
309
310 static void MCIWND_Close(MCIWndInfo* mwi)
311 {
312    MCI_GENERIC_PARMS    mgp;
313
314    memset(&mgp, 0, sizeof(mgp));
315
316    mciSendCommandA(mwi->mci, MCI_CLOSE, 0, (LPARAM)&mgp);
317 }
318
319 static LRESULT WINAPI   MCIWndProc(HWND hWnd, UINT wMsg, WPARAM lParam1, LPARAM lParam2)
320 {
321    MCIWndInfo*  mwi = (MCIWndInfo*)GetWindowLongA(hWnd, 0);
322
323    if (mwi || wMsg == WM_CREATE) {
324       switch (wMsg) {
325       case WM_CREATE:
326          MCIWND_Create(hWnd, (CREATESTRUCTA*)lParam2);
327          return 0;
328       case WM_DESTROY:
329          MCIWND_Close(mwi);
330          HeapFree(GetProcessHeap(), 0, mwi->lpName);
331          HeapFree(GetProcessHeap(), 0, mwi);
332          break;
333       case WM_PAINT:
334          MCIWND_Paint(mwi, lParam1);
335          break;
336       case WM_COMMAND:
337          return MCIWND_Command(mwi, lParam1, lParam2);
338       case WM_TIMER:
339          MCIWND_Timer(mwi, lParam1, lParam2);
340          return TRUE;
341       }
342    }
343
344    return DefWindowProcA(hWnd, wMsg, lParam1, lParam2);
345 }
346