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