]> git.sesse.net Git - vlc/blob - activex/plugin.cpp
Initial version of ActiveX plugin for VLC
[vlc] / activex / plugin.cpp
1 /*****************************************************************************\r
2  * plugin.cpp: ActiveX control for VLC\r
3  *****************************************************************************\r
4  * Copyright (C) 2005 VideoLAN\r
5  *\r
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License\r
19  * along with this program; if not, write to the Free Software\r
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.\r
21  *****************************************************************************/\r
22 \r
23 #include "plugin.h"\r
24 \r
25 #include "oleobject.h"\r
26 #include "olecontrol.h"\r
27 #include "oleinplaceobject.h"\r
28 #include "oleinplaceactiveobject.h"\r
29 #include "persistpropbag.h"\r
30 #include "persiststreaminit.h"\r
31 #include "persiststorage.h"\r
32 #include "provideclassinfo.h"\r
33 #include "connectioncontainer.h"\r
34 #include "objectsafety.h"\r
35 #include "vlccontrol.h"\r
36 \r
37 #include "utils.h"\r
38 \r
39 #include <string.h>\r
40 #include <winreg.h>\r
41 \r
42 using namespace std;\r
43 \r
44 ////////////////////////////////////////////////////////////////////////\r
45 //class factory\r
46 \r
47 // {E23FE9C6-778E-49d4-B537-38FCDE4887D8}\r
48 //const GUID CLSID_VLCPlugin = \r
49 //    { 0xe23fe9c6, 0x778e, 0x49d4, { 0xb5, 0x37, 0x38, 0xfc, 0xde, 0x48, 0x87, 0xd8 } };\r
50 \r
51 static LRESULT CALLBACK VLCInPlaceClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {\r
52     switch( uMsg )\r
53     {\r
54         case WM_ERASEBKGND:\r
55             return 1L;\r
56 \r
57         case WM_PAINT:\r
58             PAINTSTRUCT ps;\r
59             if( GetUpdateRect(hWnd, NULL, FALSE) )\r
60             {\r
61                 BeginPaint(hWnd, &ps);\r
62                 EndPaint(hWnd, &ps);\r
63             }\r
64             return 0L;\r
65 \r
66         default:\r
67             return DefWindowProc(hWnd, uMsg, wParam, lParam);\r
68     }\r
69 };\r
70 \r
71 static LRESULT CALLBACK VLCVideoClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {\r
72     VLCPlugin *p_instance = reinterpret_cast<VLCPlugin *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));\r
73 \r
74     switch( uMsg )\r
75     {\r
76         case WM_ERASEBKGND:\r
77             return 1L;\r
78 \r
79         case WM_PAINT:\r
80             PAINTSTRUCT ps;\r
81             RECT pr;\r
82             if( GetUpdateRect(hWnd, &pr, FALSE) )\r
83             {\r
84                 BeginPaint(hWnd, &ps);\r
85                 p_instance->onPaint(ps, pr);\r
86                 EndPaint(hWnd, &ps);\r
87             }\r
88             return 0L;\r
89 \r
90         default:\r
91             return DefWindowProc(hWnd, uMsg, wParam, lParam);\r
92     }\r
93 };\r
94 \r
95 VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance) :\r
96     _p_class_ref(p_class_ref),\r
97     _hinstance(hInstance)\r
98 {\r
99     WNDCLASS wClass;\r
100 \r
101     if( ! GetClassInfo(hInstance, getInPlaceWndClassName(), &wClass) )\r
102     {\r
103         wClass.style          = CS_NOCLOSE|CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;\r
104         wClass.lpfnWndProc    = VLCInPlaceClassWndProc;\r
105         wClass.cbClsExtra     = 0;\r
106         wClass.cbWndExtra     = 0;\r
107         wClass.hInstance      = hInstance;\r
108         wClass.hIcon          = NULL;\r
109         wClass.hCursor        = LoadCursor(NULL, IDC_ARROW);\r
110         wClass.hbrBackground  = NULL;\r
111         wClass.lpszMenuName   = NULL;\r
112         wClass.lpszClassName  = getInPlaceWndClassName();\r
113        \r
114         _inplace_wndclass_atom = RegisterClass(&wClass);\r
115     }\r
116     else\r
117     {\r
118         _inplace_wndclass_atom = 0;\r
119     }\r
120 \r
121     if( ! GetClassInfo(hInstance, getVideoWndClassName(), &wClass) )\r
122     {\r
123         wClass.style          = CS_NOCLOSE|CS_HREDRAW|CS_VREDRAW;\r
124         wClass.lpfnWndProc    = VLCVideoClassWndProc;\r
125         wClass.cbClsExtra     = 0;\r
126         wClass.cbWndExtra     = 0;\r
127         wClass.hInstance      = hInstance;\r
128         wClass.hIcon          = NULL;\r
129         wClass.hCursor        = LoadCursor(NULL, IDC_ARROW);\r
130         wClass.hbrBackground  = NULL;\r
131         wClass.lpszMenuName   = NULL;\r
132         wClass.lpszClassName  = getVideoWndClassName();\r
133        \r
134         _video_wndclass_atom = RegisterClass(&wClass);\r
135     }\r
136     else\r
137     {\r
138         _video_wndclass_atom = 0;\r
139     }\r
140 \r
141     _inplace_hbitmap = (HBITMAP)LoadImage(getHInstance(), TEXT("INPLACE-PICT"), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);\r
142 \r
143     AddRef();\r
144 };\r
145 \r
146 VLCPluginClass::~VLCPluginClass()\r
147 {\r
148     if( 0 != _inplace_wndclass_atom )\r
149         UnregisterClass(MAKEINTATOM(_inplace_wndclass_atom), _hinstance);\r
150 \r
151     if( 0 != _video_wndclass_atom )\r
152         UnregisterClass(MAKEINTATOM(_video_wndclass_atom), _hinstance);\r
153 \r
154     if( NULL != _inplace_hbitmap )\r
155         DeleteObject(_inplace_hbitmap);\r
156 };\r
157 \r
158 STDMETHODIMP VLCPluginClass::QueryInterface(REFIID riid, void **ppv)\r
159 {\r
160     if( NULL == ppv )\r
161         return E_INVALIDARG;\r
162 \r
163     if( (IID_IUnknown == riid) || (IID_IClassFactory == riid) )\r
164     {\r
165         AddRef();\r
166         *ppv = reinterpret_cast<LPVOID>(this);\r
167 \r
168         return NOERROR;\r
169     }\r
170 \r
171     *ppv = NULL;\r
172 \r
173     return E_NOINTERFACE;\r
174 };\r
175 \r
176 STDMETHODIMP_(ULONG) VLCPluginClass::AddRef(void)\r
177 {\r
178     return InterlockedIncrement(_p_class_ref);\r
179 };\r
180 \r
181 STDMETHODIMP_(ULONG) VLCPluginClass::Release(void)\r
182 {\r
183     ULONG refcount = InterlockedDecrement(_p_class_ref);\r
184     if( 0 == refcount )\r
185     {\r
186         delete this;\r
187         return 0;\r
188     }\r
189     return refcount;\r
190 };\r
191 \r
192 STDMETHODIMP VLCPluginClass::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv)\r
193 {\r
194     if( NULL == ppv )\r
195         return E_POINTER;\r
196 \r
197     *ppv = NULL;\r
198 \r
199     if( NULL != pUnkOuter )\r
200         return CLASS_E_NOAGGREGATION;\r
201 \r
202     VLCPlugin *plugin = new VLCPlugin(this);\r
203     if( NULL != plugin )\r
204     {\r
205         HRESULT hr = plugin->QueryInterface(riid, ppv);\r
206         plugin->Release();\r
207         return hr;\r
208     }\r
209     return E_OUTOFMEMORY;\r
210 };\r
211 \r
212 STDMETHODIMP VLCPluginClass::LockServer(BOOL fLock)\r
213 {\r
214     if( fLock )\r
215         AddRef();\r
216     else \r
217         Release();\r
218 \r
219     return S_OK;\r
220 };\r
221 \r
222 ////////////////////////////////////////////////////////////////////////\r
223 \r
224 VLCPlugin::VLCPlugin(VLCPluginClass *p_class) :\r
225     _inplacewnd(NULL),\r
226     _p_class(p_class),\r
227     _i_ref(1UL),\r
228     _codepage(CP_ACP),\r
229     _psz_src(NULL),\r
230     _b_autostart(TRUE),\r
231     _b_loopmode(FALSE),\r
232     _b_showdisplay(TRUE),\r
233     _b_sendevents(TRUE),\r
234     _i_vlc(0)\r
235 {\r
236     p_class->AddRef();\r
237 \r
238     vlcOleObject = new VLCOleObject(this);\r
239     vlcOleControl = new VLCOleControl(this);\r
240     vlcOleInPlaceObject = new VLCOleInPlaceObject(this);\r
241     vlcOleInPlaceActiveObject = new VLCOleInPlaceActiveObject(this);\r
242     vlcPersistStorage = new VLCPersistStorage(this);\r
243     vlcPersistStreamInit = new VLCPersistStreamInit(this);\r
244     vlcPersistPropertyBag = new VLCPersistPropertyBag(this);\r
245     vlcProvideClassInfo = new VLCProvideClassInfo(this);\r
246     vlcConnectionPointContainer = new VLCConnectionPointContainer(this);\r
247     vlcObjectSafety = new VLCObjectSafety(this);\r
248     vlcControl = new VLCControl(this);\r
249 };\r
250 \r
251 VLCPlugin::~VLCPlugin()\r
252 {\r
253     vlcOleInPlaceObject->UIDeactivate();\r
254     vlcOleInPlaceObject->InPlaceDeactivate();\r
255 \r
256     delete vlcControl;\r
257     delete vlcObjectSafety;\r
258     delete vlcConnectionPointContainer;\r
259     delete vlcProvideClassInfo;\r
260     delete vlcPersistPropertyBag;\r
261     delete vlcPersistStreamInit;\r
262     delete vlcPersistStorage;\r
263     delete vlcOleInPlaceActiveObject;\r
264     delete vlcOleInPlaceObject;\r
265     delete vlcOleControl;\r
266     delete vlcOleObject;\r
267 \r
268     if( _psz_src )\r
269         free(_psz_src);\r
270 \r
271     _p_class->Release();\r
272 };\r
273 \r
274 STDMETHODIMP VLCPlugin::QueryInterface(REFIID riid, void **ppv)\r
275 {\r
276     if( NULL == ppv )\r
277         return E_INVALIDARG;\r
278 \r
279     if( IID_IUnknown == riid )\r
280     {\r
281         AddRef();\r
282         *ppv = reinterpret_cast<LPVOID>(this);\r
283         return NOERROR;\r
284     }\r
285     else if( IID_IOleObject == riid )\r
286     {\r
287         AddRef();\r
288         *ppv = reinterpret_cast<LPVOID>(vlcOleObject);\r
289         return NOERROR;\r
290     }\r
291     else if( IID_IOleControl == riid )\r
292     {\r
293         AddRef();\r
294         *ppv = reinterpret_cast<LPVOID>(vlcOleControl);\r
295         return NOERROR;\r
296     }\r
297     else if( IID_IOleWindow == riid )\r
298     {\r
299         AddRef();\r
300         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceObject);\r
301         return NOERROR;\r
302     }\r
303     else if( IID_IOleInPlaceObject == riid )\r
304     {\r
305         AddRef();\r
306         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceObject);\r
307         return NOERROR;\r
308     }\r
309     else if( IID_IOleInPlaceActiveObject == riid )\r
310     {\r
311         AddRef();\r
312         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceActiveObject);\r
313         return NOERROR;\r
314     }\r
315     else if( IID_IPersist == riid )\r
316     {\r
317         AddRef();\r
318         *ppv = reinterpret_cast<LPVOID>(vlcPersistPropertyBag);\r
319         return NOERROR;\r
320     }\r
321     else if( IID_IPersistStreamInit == riid )\r
322     {\r
323         AddRef();\r
324         *ppv = reinterpret_cast<LPVOID>(vlcPersistStreamInit);\r
325         return NOERROR;\r
326     }\r
327     else if( IID_IPersistStorage == riid )\r
328     {\r
329         AddRef();\r
330         *ppv = reinterpret_cast<LPVOID>(vlcPersistStorage);\r
331         return NOERROR;\r
332     }\r
333     else if( IID_IPersistPropertyBag == riid )\r
334     {\r
335         AddRef();\r
336         *ppv = reinterpret_cast<LPVOID>(vlcPersistPropertyBag);\r
337         return NOERROR;\r
338     }\r
339     else if( IID_IProvideClassInfo == riid )\r
340     {\r
341         AddRef();\r
342         *ppv = reinterpret_cast<LPVOID>(vlcProvideClassInfo);\r
343         return NOERROR;\r
344     }\r
345     else if( IID_IProvideClassInfo2 == riid )\r
346     {\r
347         AddRef();\r
348         *ppv = reinterpret_cast<LPVOID>(vlcProvideClassInfo);\r
349         return NOERROR;\r
350     }\r
351     else if( IID_IConnectionPointContainer == riid )\r
352     {\r
353         AddRef();\r
354         *ppv = reinterpret_cast<LPVOID>(vlcConnectionPointContainer);\r
355         return NOERROR;\r
356     }\r
357     else if( IID_IObjectSafety == riid )\r
358     {\r
359         AddRef();\r
360         *ppv = reinterpret_cast<LPVOID>(vlcObjectSafety);\r
361         return NOERROR;\r
362     }\r
363     else if( IID_IDispatch == riid )\r
364     {\r
365         AddRef();\r
366         *ppv = reinterpret_cast<LPVOID>(vlcControl);\r
367         return NOERROR;\r
368     }\r
369     else if( IID_IVLCControl == riid )\r
370     {\r
371         AddRef();\r
372         *ppv = reinterpret_cast<LPVOID>(vlcControl);\r
373         return NOERROR;\r
374     }\r
375 \r
376     *ppv = NULL;\r
377 \r
378     return E_NOINTERFACE;\r
379 };\r
380 \r
381 STDMETHODIMP_(ULONG) VLCPlugin::AddRef(void)\r
382 {\r
383     return InterlockedIncrement((LONG *)&_i_ref);\r
384 };\r
385 \r
386 STDMETHODIMP_(ULONG) VLCPlugin::Release(void)\r
387 {\r
388     if( ! InterlockedDecrement((LONG *)&_i_ref) )\r
389     {\r
390         delete this;\r
391         return 0;\r
392     }\r
393     return _i_ref;\r
394 };\r
395 \r
396 //////////////////////////////////////\r
397 \r
398 /*\r
399 ** we use an in-place child window to represent plugin viewport,\r
400 ** whose size is limited by the clipping rectangle\r
401 ** all drawing within this window must follow \r
402 ** cartesian coordinate system represented by _bounds.\r
403 */\r
404 \r
405 void VLCPlugin::calcPositionChange(LPRECT lprPosRect, LPCRECT lprcClipRect)\r
406 {\r
407     _bounds.right  = lprPosRect->right-lprPosRect->left;\r
408 \r
409     if( lprcClipRect->left <= lprPosRect->left )\r
410     {\r
411         // left side is not clipped out\r
412         _bounds.left = 0;\r
413 \r
414         if( lprcClipRect->right >= lprPosRect->right )\r
415         {\r
416             // right side is not clipped out, no change\r
417         }\r
418         else if( lprcClipRect->right >= lprPosRect->left )\r
419         {\r
420             // right side is clipped out\r
421             lprPosRect->right = lprcClipRect->right;\r
422         }\r
423         else\r
424         {\r
425             // outside of clipping rectange, not visible\r
426             lprPosRect->right = lprPosRect->left;\r
427         }\r
428     }\r
429     else\r
430     {\r
431         // left side is clipped out\r
432         _bounds.left = lprPosRect->left-lprcClipRect->left;\r
433         _bounds.right += _bounds.left;\r
434 \r
435         lprPosRect->left = lprcClipRect->left;\r
436         if( lprcClipRect->right >= lprPosRect->right )\r
437         {\r
438             // right side is not clipped out\r
439         }\r
440         else\r
441         {\r
442             // right side is clipped out\r
443             lprPosRect->right = lprcClipRect->right;\r
444         }\r
445     }\r
446 \r
447     _bounds.bottom = lprPosRect->bottom-lprPosRect->top;\r
448 \r
449     if( lprcClipRect->top <= lprPosRect->top )\r
450     {\r
451         // top side is not clipped out\r
452         _bounds.top = 0;\r
453 \r
454         if( lprcClipRect->bottom >= lprPosRect->bottom )\r
455         {\r
456             // bottom side is not clipped out, no change\r
457         }\r
458         else if( lprcClipRect->bottom >= lprPosRect->top )\r
459         {\r
460             // bottom side is clipped out\r
461             lprPosRect->bottom = lprcClipRect->bottom;\r
462         }\r
463         else\r
464         {\r
465             // outside of clipping rectange, not visible\r
466             lprPosRect->right = lprPosRect->left;\r
467         }\r
468     }\r
469     else\r
470     {\r
471         _bounds.top = lprPosRect->top-lprcClipRect->top;\r
472         _bounds.bottom += _bounds.top;\r
473 \r
474         lprPosRect->top = lprcClipRect->top;\r
475         if( lprcClipRect->bottom >= lprPosRect->bottom )\r
476         {\r
477             // bottom side is not clipped out\r
478         }\r
479         else\r
480         {\r
481             // bottom side is clipped out\r
482             lprPosRect->bottom = lprcClipRect->bottom;\r
483         }\r
484     }\r
485 };\r
486 \r
487 HRESULT VLCPlugin::onInitNew(void)\r
488 {\r
489     if( 0 == _i_vlc )\r
490     {\r
491         char *ppsz_argv[] = { "vlc", "-vv" };\r
492         HKEY h_key;\r
493         DWORD i_type, i_data = MAX_PATH + 1;\r
494         char p_data[MAX_PATH + 1];\r
495         if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\VideoLAN\\VLC",\r
496                           0, KEY_READ, &h_key ) == ERROR_SUCCESS )\r
497         {\r
498              if( RegQueryValueEx( h_key, "InstallDir", 0, &i_type,\r
499                                   (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS )\r
500              {\r
501                  if( i_type == REG_SZ )\r
502                  {\r
503                      strcat( p_data, "\\vlc" );\r
504                      ppsz_argv[0] = p_data;\r
505                  }\r
506              }\r
507              RegCloseKey( h_key );\r
508         }\r
509 \r
510 #if 0\r
511         ppsz_argv[0] = "C:\\cygwin\\home\\Damien_Fouilleul\\dev\\videolan\\vlc-trunk\\vlc";\r
512 #endif\r
513 \r
514         _i_vlc = VLC_Create();\r
515         \r
516         if( VLC_Init(_i_vlc, sizeof(ppsz_argv)/sizeof(char*), ppsz_argv) )\r
517         {\r
518             VLC_Destroy(_i_vlc);\r
519             _i_vlc = 0;\r
520             return E_FAIL;\r
521         }\r
522         return S_OK;\r
523     }\r
524     return E_UNEXPECTED;\r
525 };\r
526     \r
527 HRESULT VLCPlugin::onClose(DWORD dwSaveOption)\r
528 {\r
529     if( _i_vlc )\r
530     {\r
531         if( isInPlaceActive() )\r
532         {\r
533             onInPlaceDeactivate();\r
534         }\r
535 \r
536         VLC_CleanUp(_i_vlc);\r
537         VLC_Destroy(_i_vlc);\r
538         _i_vlc = 0;\r
539     }\r
540     return S_OK;\r
541 };\r
542 \r
543 BOOL VLCPlugin::isInPlaceActive(void)\r
544 {\r
545     return (NULL != _inplacewnd);\r
546 };\r
547 \r
548 HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprcPosRect, LPCRECT lprcClipRect)\r
549 {\r
550     RECT posRect = *lprcPosRect;\r
551 \r
552     calcPositionChange(&posRect, lprcClipRect);\r
553 \r
554     _inplacewnd = CreateWindow(_p_class->getInPlaceWndClassName(),\r
555             "VLC Plugin In-Place Window",\r
556             WS_CHILD|WS_CLIPCHILDREN|WS_TABSTOP,\r
557             posRect.left,\r
558             posRect.top,\r
559             posRect.right-posRect.left,\r
560             posRect.bottom-posRect.top,\r
561             hwndParent,\r
562             0,\r
563             _p_class->getHInstance(),\r
564             NULL\r
565            );\r
566 \r
567     if( NULL == _inplacewnd )\r
568         return E_FAIL;\r
569 \r
570     SetWindowLongPtr(_inplacewnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));\r
571 \r
572     _videownd = CreateWindow(_p_class->getVideoWndClassName(),\r
573             "VLC Plugin Video Window",\r
574             WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE,\r
575             _bounds.left,\r
576             _bounds.top,\r
577             _bounds.right-_bounds.left,\r
578             _bounds.bottom-_bounds.top,\r
579             _inplacewnd,\r
580             0,\r
581             _p_class->getHInstance(),\r
582             NULL\r
583            );\r
584 \r
585     if( NULL == _videownd )\r
586     {\r
587         DestroyWindow(_inplacewnd);\r
588         return E_FAIL;\r
589     }\r
590 \r
591     SetWindowLongPtr(_videownd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));\r
592 \r
593     /* horrible cast there */\r
594     vlc_value_t val;\r
595     val.i_int = reinterpret_cast<int>(_videownd);\r
596     VLC_VariableSet(_i_vlc, "drawable", val);\r
597 \r
598     setVisible(_b_showdisplay);\r
599 \r
600     if( NULL != _psz_src )\r
601     {\r
602         // add target to playlist\r
603         char *cOptions[1];\r
604         int  cOptionsCount = 0;\r
605 \r
606         if( _b_loopmode )\r
607         {\r
608             cOptions[cOptionsCount++] = "loop";\r
609         }\r
610         VLC_AddTarget(_i_vlc, _psz_src, (const char **)&cOptions, cOptionsCount, PLAYLIST_APPEND, PLAYLIST_END);\r
611 \r
612         if( _b_autostart )\r
613         {\r
614             VLC_Play(_i_vlc);\r
615             fireOnPlayEvent();\r
616         }\r
617     }\r
618     return S_OK;\r
619 };\r
620 \r
621 HRESULT VLCPlugin::onInPlaceDeactivate(void)\r
622 {\r
623     VLC_Stop(_i_vlc);\r
624     fireOnStopEvent();\r
625 \r
626     DestroyWindow(_videownd);\r
627     _videownd = NULL;\r
628     DestroyWindow(_inplacewnd);\r
629     _inplacewnd = NULL;\r
630  \r
631     return S_OK;\r
632 };\r
633 \r
634 BOOL VLCPlugin::isVisible(void)\r
635 {\r
636     return GetWindowLong(_inplacewnd, GWL_STYLE) & WS_VISIBLE;\r
637 };\r
638 \r
639 void VLCPlugin::setVisible(BOOL fVisible)\r
640 {\r
641     ShowWindow(_inplacewnd, fVisible ? SW_SHOW : SW_HIDE);\r
642 };\r
643 \r
644 void VLCPlugin::setFocus(BOOL fFocus)\r
645 {\r
646     if( fFocus )\r
647         SetActiveWindow(_inplacewnd);\r
648 };\r
649 \r
650 BOOL VLCPlugin::hasFocus(void)\r
651 {\r
652     return GetActiveWindow() == _inplacewnd;\r
653 };\r
654 \r
655 void VLCPlugin::onPaint(PAINTSTRUCT &ps, RECT &pr)\r
656 {\r
657     /*\r
658     ** if VLC is playing, it may not display any VIDEO content \r
659     ** hence, draw control logo\r
660     */ \r
661     int width = _bounds.right-_bounds.left;\r
662     int height = _bounds.bottom-_bounds.top;\r
663 \r
664     HBITMAP pict = _p_class->getInPlacePict();\r
665     if( NULL != pict )\r
666     {\r
667         HDC hdcPict = CreateCompatibleDC(ps.hdc);\r
668         if( NULL != hdcPict )\r
669         {\r
670             BITMAP bm;\r
671             if( GetObject(pict, sizeof(BITMAPINFO), &bm) )\r
672             {\r
673                 int dstWidth = bm.bmWidth;\r
674                 if( dstWidth > width-4 )\r
675                     dstWidth = width-4;\r
676 \r
677                 int dstHeight = bm.bmHeight;\r
678                 if( dstHeight > height-4 )\r
679                     dstHeight = height-4;\r
680 \r
681                 int dstX = (width-dstWidth)/2;\r
682                 int dstY = (height-dstHeight)/2;\r
683 \r
684                 SelectObject(hdcPict, pict);\r
685                 StretchBlt(ps.hdc, dstX, dstY, dstWidth, dstHeight,\r
686                         hdcPict, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);\r
687                 DeleteDC(hdcPict);\r
688                 ExcludeClipRect(ps.hdc, dstX, dstY, dstWidth+dstX, dstHeight+dstY);\r
689             }\r
690         }\r
691     }\r
692 \r
693     FillRect(ps.hdc, &pr, (HBRUSH)GetStockObject(WHITE_BRUSH));\r
694     SelectObject(ps.hdc, GetStockObject(BLACK_BRUSH));\r
695 \r
696     MoveToEx(ps.hdc, 0, 0, NULL);\r
697     LineTo(ps.hdc, width-1, 0);\r
698     LineTo(ps.hdc, width-1, height-1);\r
699     LineTo(ps.hdc, 0, height-1);\r
700     LineTo(ps.hdc, 0, 0);\r
701 };\r
702 \r
703 void VLCPlugin::onPositionChange(LPCRECT lprcPosRect, LPCRECT lprcClipRect)\r
704 {\r
705     RECT posRect = *lprcPosRect;\r
706 \r
707     calcPositionChange(&posRect, lprcClipRect);\r
708 \r
709     /*\r
710     ** change in-place window geometry to match clipping region\r
711     */\r
712     MoveWindow(_inplacewnd,\r
713             posRect.left,\r
714             posRect.top,\r
715             posRect.right-posRect.left,\r
716             posRect.bottom-posRect.top,\r
717             FALSE);\r
718 \r
719     /*\r
720     ** change video window geometry to match object bounds within clipping region\r
721     */\r
722     MoveWindow(_videownd,\r
723             _bounds.left,\r
724             _bounds.top,\r
725             _bounds.right-_bounds.left,\r
726             _bounds.bottom-_bounds.top,\r
727             FALSE);\r
728 \r
729     RECT updateRect;\r
730 \r
731     updateRect.left = -_bounds.left;\r
732     updateRect.top = -_bounds.top;\r
733     updateRect.right = _bounds.right-_bounds.left;\r
734     updateRect.bottom = _bounds.bottom-_bounds.top;\r
735 \r
736     ValidateRect(_videownd, NULL);\r
737     InvalidateRect(_videownd, &updateRect, FALSE);\r
738     UpdateWindow(_videownd);\r
739 };\r
740 \r
741 void VLCPlugin::fireOnPlayEvent(void)\r
742 {\r
743     if( _b_sendevents )\r
744     {\r
745         DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};\r
746         vlcConnectionPointContainer->fireEvent(1, LOCALE_USER_DEFAULT, &dispparamsNoArgs); \r
747     }\r
748 };\r
749 \r
750 void VLCPlugin::fireOnPauseEvent(void)\r
751 {\r
752     if( _b_sendevents )\r
753     {\r
754         DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};\r
755         vlcConnectionPointContainer->fireEvent(2, LOCALE_USER_DEFAULT, &dispparamsNoArgs); \r
756     }\r
757 };\r
758 \r
759 void VLCPlugin::fireOnStopEvent(void)\r
760 {\r
761     if( _b_sendevents )\r
762     {\r
763         DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};\r
764         vlcConnectionPointContainer->fireEvent(3, LOCALE_USER_DEFAULT, &dispparamsNoArgs); \r
765     }\r
766 };\r
767 \r