]> git.sesse.net Git - vlc/blob - projects/activex/plugin.cpp
434f582e09e5ccf50d4a1554bee344a895294624
[vlc] / projects / activex / plugin.cpp
1 /*****************************************************************************
2  * plugin.cpp: ActiveX control for VLC
3  *****************************************************************************
4  * Copyright (C) 2006-2010 the VideoLAN team
5  *
6  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7  *          Jean-Paul Saman <jpsaman@videolan.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "plugin.h"
25
26 #include "oleobject.h"
27 #include "olecontrol.h"
28 #include "oleinplaceobject.h"
29 #include "oleinplaceactiveobject.h"
30 #include "persistpropbag.h"
31 #include "persiststreaminit.h"
32 #include "persiststorage.h"
33 #include "provideclassinfo.h"
34 #include "connectioncontainer.h"
35 #include "objectsafety.h"
36 #include "vlccontrol.h"
37 #include "vlccontrol2.h"
38 #include "viewobject.h"
39 #include "dataobject.h"
40 #include "supporterrorinfo.h"
41
42 #include "utils.h"
43
44 #include <stdio.h>
45 #include <string.h>
46 #include <winreg.h>
47 #include <winuser.h>
48 #include <servprov.h>
49 #include <shlwapi.h>
50 #include <wininet.h>
51 #include <assert.h>
52
53 using namespace std;
54
55 ////////////////////////////////////////////////////////////////////////
56 //class factory
57
58 static LRESULT CALLBACK VLCInPlaceClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
59     VLCPlugin *p_instance = reinterpret_cast<VLCPlugin *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
60
61     switch( uMsg )
62     {
63         case WM_ERASEBKGND:
64             return 1L;
65
66         case WM_PAINT:
67             PAINTSTRUCT ps;
68             RECT pr;
69             if( GetUpdateRect(hWnd, &pr, FALSE) )
70             {
71                 RECT bounds;
72                 GetClientRect(hWnd, &bounds);
73                 BeginPaint(hWnd, &ps);
74                 p_instance->onPaint(ps.hdc, bounds, pr);
75                 EndPaint(hWnd, &ps);
76             }
77             return 0L;
78
79         default:
80             return DefWindowProc(hWnd, uMsg, wParam, lParam);
81     }
82 };
83
84 VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance, REFCLSID rclsid) :
85     _p_class_ref(p_class_ref),
86     _hinstance(hInstance),
87     _classid(rclsid),
88     _inplace_picture(NULL)
89 {
90     WNDCLASS wClass;
91
92     if( ! GetClassInfo(hInstance, getInPlaceWndClassName(), &wClass) )
93     {
94         wClass.style          = CS_NOCLOSE|CS_DBLCLKS;
95         wClass.lpfnWndProc    = VLCInPlaceClassWndProc;
96         wClass.cbClsExtra     = 0;
97         wClass.cbWndExtra     = 0;
98         wClass.hInstance      = hInstance;
99         wClass.hIcon          = NULL;
100         wClass.hCursor        = LoadCursor(NULL, IDC_ARROW);
101         wClass.hbrBackground  = NULL;
102         wClass.lpszMenuName   = NULL;
103         wClass.lpszClassName  = getInPlaceWndClassName();
104
105         _inplace_wndclass_atom = RegisterClass(&wClass);
106     }
107     else
108     {
109         _inplace_wndclass_atom = 0;
110     }
111
112     HBITMAP hbitmap = (HBITMAP)LoadImage(getHInstance(), MAKEINTRESOURCE(2), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
113     if( NULL != hbitmap )
114     {
115         PICTDESC pictDesc;
116
117         pictDesc.cbSizeofstruct = sizeof(PICTDESC);
118         pictDesc.picType        = PICTYPE_BITMAP;
119         pictDesc.bmp.hbitmap    = hbitmap;
120         pictDesc.bmp.hpal       = NULL;
121
122         if( FAILED(OleCreatePictureIndirect(&pictDesc, IID_IPicture, TRUE, reinterpret_cast<LPVOID*>(&_inplace_picture))) )
123             _inplace_picture = NULL;
124     }
125     AddRef();
126 };
127
128 VLCPluginClass::~VLCPluginClass()
129 {
130     if( 0 != _inplace_wndclass_atom )
131         UnregisterClass(MAKEINTATOM(_inplace_wndclass_atom), _hinstance);
132
133     if( NULL != _inplace_picture )
134         _inplace_picture->Release();
135 };
136
137 STDMETHODIMP VLCPluginClass::QueryInterface(REFIID riid, void **ppv)
138 {
139     if( NULL == ppv )
140         return E_INVALIDARG;
141
142     if( (IID_IUnknown == riid)
143      || (IID_IClassFactory == riid) )
144     {
145         AddRef();
146         *ppv = reinterpret_cast<LPVOID>(this);
147
148         return NOERROR;
149     }
150
151     *ppv = NULL;
152
153     return E_NOINTERFACE;
154 };
155
156 STDMETHODIMP_(ULONG) VLCPluginClass::AddRef(void)
157 {
158     return InterlockedIncrement(_p_class_ref);
159 };
160
161 STDMETHODIMP_(ULONG) VLCPluginClass::Release(void)
162 {
163     ULONG refcount = InterlockedDecrement(_p_class_ref);
164     if( 0 == refcount )
165     {
166         delete this;
167         return 0;
168     }
169     return refcount;
170 };
171
172 STDMETHODIMP VLCPluginClass::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppv)
173 {
174     if( NULL == ppv )
175         return E_POINTER;
176
177     *ppv = NULL;
178
179     if( (NULL != pUnkOuter) && (IID_IUnknown != riid) ) {
180         return CLASS_E_NOAGGREGATION;
181     }
182
183     VLCPlugin *plugin = new VLCPlugin(this, pUnkOuter);
184     if( NULL != plugin )
185     {
186         HRESULT hr = plugin->QueryInterface(riid, ppv);
187         // the following will destroy the object if QueryInterface() failed
188         plugin->Release();
189         return hr;
190     }
191     return E_OUTOFMEMORY;
192 };
193
194 STDMETHODIMP VLCPluginClass::LockServer(BOOL fLock)
195 {
196     if( fLock )
197         AddRef();
198     else
199         Release();
200
201     return S_OK;
202 };
203
204 ////////////////////////////////////////////////////////////////////////
205
206 VLCPlugin::VLCPlugin(VLCPluginClass *p_class, LPUNKNOWN pUnkOuter) :
207     _inplacewnd(NULL),
208     _p_class(p_class),
209     _i_ref(1UL),
210     _p_libvlc(NULL),
211     _p_mlist(NULL),
212     _p_mplayer(NULL),
213     _i_midx(-1),
214     _i_codepage(CP_ACP),
215     _b_usermode(TRUE)
216 {
217     p_class->AddRef();
218
219     vlcOleControl = new VLCOleControl(this);
220     vlcOleInPlaceObject = new VLCOleInPlaceObject(this);
221     vlcOleInPlaceActiveObject = new VLCOleInPlaceActiveObject(this);
222     vlcPersistStorage = new VLCPersistStorage(this);
223     vlcPersistStreamInit = new VLCPersistStreamInit(this);
224     vlcPersistPropertyBag = new VLCPersistPropertyBag(this);
225     vlcProvideClassInfo = new VLCProvideClassInfo(this);
226     vlcConnectionPointContainer = new VLCConnectionPointContainer(this);
227     vlcObjectSafety = new VLCObjectSafety(this);
228     vlcControl = new VLCControl(this);
229     vlcControl2 = new VLCControl2(this);
230     vlcViewObject = new VLCViewObject(this);
231     vlcDataObject = new VLCDataObject(this);
232     vlcOleObject = new VLCOleObject(this);
233     vlcSupportErrorInfo = new VLCSupportErrorInfo(this);
234
235     // configure controlling IUnknown interface for implemented interfaces
236     this->pUnkOuter = (NULL != pUnkOuter) ? pUnkOuter : dynamic_cast<LPUNKNOWN>(this);
237
238     // default picure
239     _p_pict = p_class->getInPlacePict();
240
241     // make sure that persistable properties are initialized
242     onInit();
243 };
244
245 VLCPlugin::~VLCPlugin()
246 {
247     /*
248     ** bump refcount to avoid recursive release from
249     ** following interfaces when releasing this interface
250     */
251     AddRef();
252
253     delete vlcSupportErrorInfo;
254     delete vlcOleObject;
255     delete vlcDataObject;
256     delete vlcViewObject;
257     delete vlcControl2;
258     delete vlcControl;
259     delete vlcConnectionPointContainer;
260     delete vlcProvideClassInfo;
261     delete vlcPersistPropertyBag;
262     delete vlcPersistStreamInit;
263     delete vlcPersistStorage;
264     delete vlcOleInPlaceActiveObject;
265     delete vlcOleInPlaceObject;
266     delete vlcObjectSafety;
267
268     delete vlcOleControl;
269     if( _p_pict )
270         _p_pict->Release();
271
272     SysFreeString(_bstr_mrl);
273     SysFreeString(_bstr_baseurl);
274
275     if( _p_mplayer )
276     {
277         player_unregister_events();
278         libvlc_media_player_release(_p_mplayer);
279         _p_mplayer=NULL;
280     }
281     if( _p_mlist )   { libvlc_media_list_release(_p_mlist); _p_mlist=NULL; }
282     if( _p_libvlc )  { libvlc_release(_p_libvlc); _p_libvlc=NULL; }
283
284     _p_class->Release();
285 };
286
287 STDMETHODIMP VLCPlugin::QueryInterface(REFIID riid, void **ppv)
288 {
289     if( NULL == ppv )
290         return E_INVALIDARG;
291
292     if( IID_IUnknown == riid )
293         *ppv = reinterpret_cast<LPVOID>(this);
294     else if( IID_IOleObject == riid )
295         *ppv = reinterpret_cast<LPVOID>(vlcOleObject);
296     else if( IID_IOleControl == riid )
297         *ppv = reinterpret_cast<LPVOID>(vlcOleControl);
298     else if( IID_IOleWindow == riid )
299         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceObject);
300     else if( IID_IOleInPlaceObject == riid )
301         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceObject);
302     else if( IID_IOleInPlaceActiveObject == riid )
303         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceActiveObject);
304     else if( IID_IPersist == riid )
305         *ppv = reinterpret_cast<LPVOID>(vlcPersistStreamInit);
306     else if( IID_IPersistStreamInit == riid )
307         *ppv = reinterpret_cast<LPVOID>(vlcPersistStreamInit);
308     else if( IID_IPersistStorage == riid )
309         *ppv = reinterpret_cast<LPVOID>(vlcPersistStorage);
310     else if( IID_IPersistPropertyBag == riid )
311         *ppv = reinterpret_cast<LPVOID>(vlcPersistPropertyBag);
312     else if( IID_IProvideClassInfo == riid )
313         *ppv = reinterpret_cast<LPVOID>(vlcProvideClassInfo);
314     else if( IID_IProvideClassInfo2 == riid )
315         *ppv = reinterpret_cast<LPVOID>(vlcProvideClassInfo);
316     else if( IID_IConnectionPointContainer == riid )
317         *ppv = reinterpret_cast<LPVOID>(vlcConnectionPointContainer);
318     else if( IID_IObjectSafety == riid )
319         *ppv = reinterpret_cast<LPVOID>(vlcObjectSafety);
320     else if( IID_IDispatch == riid )
321         *ppv = (CLSID_VLCPlugin2 == getClassID()) ?
322                 reinterpret_cast<LPVOID>(vlcControl2) :
323                 reinterpret_cast<LPVOID>(vlcControl);
324     else if( IID_IVLCControl == riid )
325         *ppv = reinterpret_cast<LPVOID>(vlcControl);
326     else if( IID_IVLCControl2 == riid )
327         *ppv = reinterpret_cast<LPVOID>(vlcControl2);
328     else if( IID_IViewObject == riid )
329         *ppv = reinterpret_cast<LPVOID>(vlcViewObject);
330     else if( IID_IViewObject2 == riid )
331         *ppv = reinterpret_cast<LPVOID>(vlcViewObject);
332     else if( IID_IDataObject == riid )
333         *ppv = reinterpret_cast<LPVOID>(vlcDataObject);
334     else if( IID_ISupportErrorInfo == riid )
335         *ppv = reinterpret_cast<LPVOID>(vlcSupportErrorInfo);
336     else
337     {
338         *ppv = NULL;
339         return E_NOINTERFACE;
340     }
341     ((LPUNKNOWN)*ppv)->AddRef();
342     return NOERROR;
343 };
344
345 STDMETHODIMP_(ULONG) VLCPlugin::AddRef(void)
346 {
347     return InterlockedIncrement((LONG *)&_i_ref);
348 };
349
350 STDMETHODIMP_(ULONG) VLCPlugin::Release(void)
351 {
352     if( ! InterlockedDecrement((LONG *)&_i_ref) )
353     {
354         delete this;
355         return 0;
356     }
357     return _i_ref;
358 };
359
360 //////////////////////////////////////
361
362 HRESULT VLCPlugin::onInit(void)
363 {
364     if( NULL == _p_libvlc )
365     {
366         // initialize persistable properties
367         _b_autoplay   = TRUE;
368         _b_autoloop   = FALSE;
369         _b_toolbar    = FALSE;
370         _bstr_baseurl = NULL;
371         _bstr_mrl     = NULL;
372         _b_visible    = TRUE;
373         _b_mute       = FALSE;
374         _i_volume     = 50;
375         _i_time       = 0;
376         _i_backcolor  = 0;
377         // set default/preferred size (320x240) pixels in HIMETRIC
378         HDC hDC = CreateDevDC(NULL);
379         _extent.cx = 320;
380         _extent.cy = 240;
381         HimetricFromDP(hDC, (LPPOINT)&_extent, 1);
382         DeleteDC(hDC);
383
384         return S_OK;
385     }
386     return CO_E_ALREADYINITIALIZED;
387 };
388
389 HRESULT VLCPlugin::onLoad(void)
390 {
391     if( SysStringLen(_bstr_baseurl) == 0 )
392     {
393         /*
394         ** try to retreive the base URL using the client site moniker, which for Internet Explorer
395         ** is the URL of the page the plugin is embedded into.
396         */
397         LPOLECLIENTSITE pClientSite;
398         if( SUCCEEDED(vlcOleObject->GetClientSite(&pClientSite)) && (NULL != pClientSite) )
399         {
400             IBindCtx *pBC = 0;
401             if( SUCCEEDED(CreateBindCtx(0, &pBC)) )
402             {
403                 LPMONIKER pContMoniker = NULL;
404                 if( SUCCEEDED(pClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
405                                 OLEWHICHMK_CONTAINER, &pContMoniker)) )
406                 {
407                     LPOLESTR base_url;
408                     if( SUCCEEDED(pContMoniker->GetDisplayName(pBC, NULL, &base_url)) )
409                     {
410                         /*
411                         ** check that the moniker name is a URL
412                         */
413                         if( UrlIsW(base_url, URLIS_URL) )
414                         {
415                             /* copy base URL */
416                             _bstr_baseurl = SysAllocString(base_url);
417                         }
418                         CoTaskMemFree(base_url);
419                     }
420                 }
421             }
422         }
423     }
424     setDirty(FALSE);
425     return S_OK;
426 };
427
428 void VLCPlugin::initVLC()
429 {
430     extern HMODULE DllGetModule();
431
432     /*
433     ** default initialization options
434     */
435     const char *ppsz_argv[32] = { };
436     int   ppsz_argc = 0;
437
438     char p_progpath[MAX_PATH];
439     {
440         TCHAR w_progpath[MAX_PATH];
441         DWORD len = GetModuleFileName(DllGetModule(), w_progpath, MAX_PATH);
442         if( len > 0 )
443         {
444             len = WideCharToMultiByte(CP_UTF8, 0, w_progpath, len, p_progpath,
445                        sizeof(p_progpath)-1, NULL, NULL);
446             if( len > 0 )
447             {
448                 p_progpath[len] = '\0';
449                 ppsz_argv[0] = p_progpath;
450             }
451         }
452     }
453
454     ppsz_argv[ppsz_argc++] = "-vv";
455
456     HKEY h_key;
457     char p_pluginpath[MAX_PATH];
458     if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("Software\\VideoLAN\\VLC"),
459                       0, KEY_READ, &h_key ) == ERROR_SUCCESS )
460     {
461         DWORD i_type, i_data = MAX_PATH;
462         TCHAR w_pluginpath[MAX_PATH];
463         if( RegQueryValueEx( h_key, TEXT("InstallDir"), 0, &i_type,
464                              (LPBYTE)w_pluginpath, &i_data ) == ERROR_SUCCESS )
465         {
466             if( i_type == REG_SZ )
467             {
468                 if( WideCharToMultiByte(CP_UTF8, 0, w_pluginpath, -1, p_pluginpath,
469                          sizeof(p_pluginpath)-sizeof("\\plugins")+1, NULL, NULL) )
470                 {
471                     strcat( p_pluginpath, "\\plugins" );
472                     ppsz_argv[ppsz_argc++] = "--plugin-path";
473                     ppsz_argv[ppsz_argc++] = p_pluginpath;
474                 }
475             }
476         }
477         RegCloseKey( h_key );
478     }
479
480     // make sure plugin isn't affected with VLC single instance mode
481     ppsz_argv[ppsz_argc++] = "--no-one-instance";
482
483     /* common settings */
484     ppsz_argv[ppsz_argc++] = "-vv";
485     ppsz_argv[ppsz_argc++] = "--no-stats";
486     ppsz_argv[ppsz_argc++] = "--no-media-library";
487     ppsz_argv[ppsz_argc++] = "--intf=dummy";
488     ppsz_argv[ppsz_argc++] = "--no-video-title-show";
489
490
491     // loop mode is a configuration option only
492     if( _b_autoloop )
493         ppsz_argv[ppsz_argc++] = "--loop";
494
495     _p_libvlc = libvlc_new(ppsz_argc, ppsz_argv);
496     if( !_p_libvlc )
497         return;
498
499     _p_mlist = libvlc_media_list_new(_p_libvlc);
500
501     // initial playlist item
502     if( SysStringLen(_bstr_mrl) > 0 )
503     {
504         char *psz_mrl = NULL;
505
506         if( SysStringLen(_bstr_baseurl) > 0 )
507         {
508             /*
509             ** if the MRL a relative URL, we should end up with an absolute URL
510             */
511             LPWSTR abs_url = CombineURL(_bstr_baseurl, _bstr_mrl);
512             if( NULL != abs_url )
513             {
514                 psz_mrl = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url));
515                 CoTaskMemFree(abs_url);
516             }
517             else
518             {
519                 psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl);
520             }
521         }
522         else
523         {
524             /*
525             ** baseURL is empty, assume MRL is absolute
526             */
527             psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl);
528         }
529         if( NULL != psz_mrl )
530         {
531             const char *options[1];
532             int i_options = 0;
533
534             char timeBuffer[32];
535             if( _i_time )
536             {
537                 snprintf(timeBuffer, sizeof(timeBuffer), ":start-time=%d", _i_time);
538                 options[i_options++] = timeBuffer;
539             }
540             // add default target to playlist
541             playlist_add_extended_untrusted(psz_mrl, i_options, options);
542             CoTaskMemFree(psz_mrl);
543         }
544     }
545 };
546
547 void VLCPlugin::setErrorInfo(REFIID riid, const char *description)
548 {
549     vlcSupportErrorInfo->setErrorInfo( getClassID() == CLSID_VLCPlugin2 ?
550         OLESTR("VideoLAN.VLCPlugin.2") : OLESTR("VideoLAN.VLCPlugin.1"),
551         riid, description );
552 };
553
554 HRESULT VLCPlugin::onAmbientChanged(LPUNKNOWN pContainer, DISPID dispID)
555 {
556     VARIANT v;
557     switch( dispID )
558     {
559         case DISPID_AMBIENT_BACKCOLOR:
560             VariantInit(&v);
561             V_VT(&v) = VT_I4;
562             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
563             {
564                 setBackColor(V_I4(&v));
565             }
566             break;
567         case DISPID_AMBIENT_DISPLAYNAME:
568             break;
569         case DISPID_AMBIENT_FONT:
570             break;
571         case DISPID_AMBIENT_FORECOLOR:
572             break;
573         case DISPID_AMBIENT_LOCALEID:
574             break;
575         case DISPID_AMBIENT_MESSAGEREFLECT:
576             break;
577         case DISPID_AMBIENT_SCALEUNITS:
578             break;
579         case DISPID_AMBIENT_TEXTALIGN:
580             break;
581         case DISPID_AMBIENT_USERMODE:
582             VariantInit(&v);
583             V_VT(&v) = VT_BOOL;
584             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
585             {
586                 setUserMode(V_BOOL(&v) != VARIANT_FALSE);
587             }
588             break;
589         case DISPID_AMBIENT_UIDEAD:
590             break;
591         case DISPID_AMBIENT_SHOWGRABHANDLES:
592             break;
593         case DISPID_AMBIENT_SHOWHATCHING:
594             break;
595         case DISPID_AMBIENT_DISPLAYASDEFAULT:
596             break;
597         case DISPID_AMBIENT_SUPPORTSMNEMONICS:
598             break;
599         case DISPID_AMBIENT_AUTOCLIP:
600             break;
601         case DISPID_AMBIENT_APPEARANCE:
602             break;
603         case DISPID_AMBIENT_CODEPAGE:
604             VariantInit(&v);
605             V_VT(&v) = VT_I4;
606             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
607             {
608                 setCodePage(V_I4(&v));
609             }
610             break;
611         case DISPID_AMBIENT_PALETTE:
612             break;
613         case DISPID_AMBIENT_CHARSET:
614             break;
615         case DISPID_AMBIENT_RIGHTTOLEFT:
616             break;
617         case DISPID_AMBIENT_TOPTOBOTTOM:
618             break;
619         case DISPID_UNKNOWN:
620             /*
621             ** multiple property change, look up the ones we are interested in
622             */
623             VariantInit(&v);
624             V_VT(&v) = VT_BOOL;
625             if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_USERMODE, v)) )
626             {
627                 setUserMode(V_BOOL(&v) != VARIANT_FALSE);
628             }
629             VariantInit(&v);
630             V_VT(&v) = VT_I4;
631             if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_CODEPAGE, v)) )
632             {
633                 setCodePage(V_I4(&v));
634             }
635             break;
636     }
637     return S_OK;
638 };
639
640 HRESULT VLCPlugin::onClose(DWORD dwSaveOption)
641 {
642     if( isInPlaceActive() )
643     {
644         onInPlaceDeactivate();
645     }
646     if( isRunning() )
647     {
648         libvlc_instance_t* p_libvlc = _p_libvlc;
649
650         _p_libvlc = NULL;
651         vlcDataObject->onClose();
652
653         if( p_libvlc )
654             libvlc_release(p_libvlc);
655     }
656     return S_OK;
657 };
658
659 BOOL VLCPlugin::isInPlaceActive(void)
660 {
661     return (NULL != _inplacewnd);
662 };
663
664 HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprcPosRect, LPCRECT lprcClipRect)
665 {
666     RECT clipRect = *lprcClipRect;
667
668     /*
669     ** record keeping of control geometry within container
670     */
671     _posRect = *lprcPosRect;
672
673     /*
674     ** Create a window for in place activated control.
675     ** the window geometry matches the control viewport
676     ** within container so that embedded video is always
677     ** properly displayed.
678     */
679     _inplacewnd = CreateWindow(_p_class->getInPlaceWndClassName(),
680             TEXT("VLC Plugin In-Place Window"),
681             WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
682             lprcPosRect->left,
683             lprcPosRect->top,
684             lprcPosRect->right-lprcPosRect->left,
685             lprcPosRect->bottom-lprcPosRect->top,
686             hwndParent,
687             0,
688             _p_class->getHInstance(),
689             NULL
690            );
691
692     if( NULL == _inplacewnd )
693         return E_FAIL;
694
695     SetWindowLongPtr(_inplacewnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
696
697     /* change cliprect coordinates system relative to window bounding rect */
698     OffsetRect(&clipRect, -lprcPosRect->left, -lprcPosRect->top);
699
700     HRGN clipRgn = CreateRectRgnIndirect(&clipRect);
701     SetWindowRgn(_inplacewnd, clipRgn, TRUE);
702
703     if( _b_usermode )
704     {
705         /* will run vlc if not done already */
706         libvlc_instance_t* p_libvlc;
707         HRESULT result = getVLC(&p_libvlc);
708         if( FAILED(result) )
709             return result;
710
711         if( _b_autoplay && playlist_select(0) )
712         {
713             libvlc_media_player_play(_p_mplayer);
714             fireOnPlayEvent();
715         }
716     }
717
718     if( isVisible() )
719         ShowWindow(_inplacewnd, SW_SHOW);
720
721     return S_OK;
722 };
723
724 HRESULT VLCPlugin::onInPlaceDeactivate(void)
725 {
726     if( isPlaying() )
727     {
728         playlist_stop();
729         fireOnStopEvent();
730     }
731
732     DestroyWindow(_inplacewnd);
733     _inplacewnd = NULL;
734
735     return S_OK;
736 };
737
738 void VLCPlugin::setVisible(BOOL fVisible)
739 {
740     if( fVisible != _b_visible )
741     {
742         _b_visible = fVisible;
743         if( isInPlaceActive() )
744         {
745             ShowWindow(_inplacewnd, fVisible ? SW_SHOW : SW_HIDE);
746             if( fVisible )
747                 InvalidateRect(_inplacewnd, NULL, TRUE);
748         }
749         setDirty(TRUE);
750         firePropChangedEvent(DISPID_Visible);
751     }
752 };
753
754 void VLCPlugin::setVolume(int volume)
755 {
756     if( volume < 0 )
757         volume = 0;
758     else if( volume > 200 )
759         volume = 200;
760
761     if( volume != _i_volume )
762     {
763         _i_volume = volume;
764         if( isRunning() )
765         {
766             libvlc_media_player_t *p_md;
767             HRESULT hr = getMD(&p_md);
768             if( SUCCEEDED(hr) )
769                 libvlc_audio_set_volume(p_md, _i_volume);
770         }
771         setDirty(TRUE);
772     }
773 };
774
775 void VLCPlugin::setBackColor(OLE_COLOR backcolor)
776 {
777     if( _i_backcolor != backcolor )
778     {
779         _i_backcolor = backcolor;
780         if( isInPlaceActive() )
781         {
782
783         }
784         setDirty(TRUE);
785     }
786 };
787
788 void VLCPlugin::setTime(int seconds)
789 {
790     if( seconds < 0 )
791         seconds = 0;
792
793     if( seconds != _i_time )
794     {
795         setStartTime(_i_time);
796         if( NULL != _p_mplayer )
797         {
798             libvlc_media_player_set_time(_p_mplayer, _i_time);
799         }
800     }
801 };
802
803 void VLCPlugin::setFocus(BOOL fFocus)
804 {
805     if( fFocus )
806         SetActiveWindow(_inplacewnd);
807 };
808
809 BOOL VLCPlugin::hasFocus(void)
810 {
811     return GetActiveWindow() == _inplacewnd;
812 };
813
814 void VLCPlugin::onDraw(DVTARGETDEVICE * ptd, HDC hicTargetDev,
815         HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds)
816 {
817     if( isVisible() )
818     {
819         long width = lprcBounds->right-lprcBounds->left;
820         long height = lprcBounds->bottom-lprcBounds->top;
821
822         RECT bounds = { lprcBounds->left, lprcBounds->top, lprcBounds->right, lprcBounds->bottom };
823
824         if( isUserMode() )
825         {
826             /* VLC is in user mode, just draw background color */
827             COLORREF colorref = RGB(0, 0, 0);
828             OleTranslateColor(_i_backcolor, (HPALETTE)GetStockObject(DEFAULT_PALETTE), &colorref);
829             if( colorref != RGB(0, 0, 0) )
830             {
831                 /* custom background */
832                 HBRUSH colorbrush = CreateSolidBrush(colorref);
833                 FillRect(hdcDraw, &bounds, colorbrush);
834                 DeleteObject((HANDLE)colorbrush);
835             }
836             else
837             {
838                 /* black background */
839                 FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(BLACK_BRUSH));
840             }
841         }
842         else
843         {
844             /* VLC is in design mode, draw the VLC logo */
845             FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(WHITE_BRUSH));
846
847             LPPICTURE pict = getPicture();
848             if( NULL != pict )
849             {
850                 OLE_XSIZE_HIMETRIC picWidth;
851                 OLE_YSIZE_HIMETRIC picHeight;
852
853                 pict->get_Width(&picWidth);
854                 pict->get_Height(&picHeight);
855
856                 SIZEL picSize = { picWidth, picHeight };
857
858                 if( NULL != hicTargetDev )
859                 {
860                     DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1);
861                 }
862                 else if( NULL != (hicTargetDev = CreateDevDC(ptd)) )
863                 {
864                     DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1);
865                     DeleteDC(hicTargetDev);
866                 }
867
868                 if( picSize.cx > width-4 )
869                     picSize.cx = width-4;
870                 if( picSize.cy > height-4 )
871                     picSize.cy = height-4;
872
873                 LONG dstX = lprcBounds->left+(width-picSize.cx)/2;
874                 LONG dstY = lprcBounds->top+(height-picSize.cy)/2;
875
876                 if( NULL != lprcWBounds )
877                 {
878                     RECT wBounds = { lprcWBounds->left, lprcWBounds->top, lprcWBounds->right, lprcWBounds->bottom };
879                     pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy,
880                             0L, picHeight, picWidth, -picHeight, &wBounds);
881                 }
882                 else
883                     pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy,
884                             0L, picHeight, picWidth, -picHeight, NULL);
885
886                 pict->Release();
887             }
888
889             SelectObject(hdcDraw, GetStockObject(BLACK_BRUSH));
890
891             MoveToEx(hdcDraw, bounds.left, bounds.top, NULL);
892             LineTo(hdcDraw, bounds.left+width-1, bounds.top);
893             LineTo(hdcDraw, bounds.left+width-1, bounds.top+height-1);
894             LineTo(hdcDraw, bounds.left, bounds.top+height-1);
895             LineTo(hdcDraw, bounds.left, bounds.top);
896         }
897     }
898 };
899
900 void VLCPlugin::onPaint(HDC hdc, const RECT &bounds, const RECT &clipRect)
901 {
902     if( isVisible() )
903     {
904         /* if VLC is in design mode, draw control logo */
905         HDC hdcDraw = CreateCompatibleDC(hdc);
906         if( NULL != hdcDraw )
907         {
908             SIZEL size = getExtent();
909             DPFromHimetric(hdc, (LPPOINT)&size, 1);
910             RECTL posRect = { 0, 0, size.cx, size.cy };
911
912             int width = bounds.right-bounds.left;
913             int height = bounds.bottom-bounds.top;
914
915             HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
916             if( NULL != hBitmap )
917             {
918                 HBITMAP oldBmp = (HBITMAP)SelectObject(hdcDraw, hBitmap);
919
920                 if( (size.cx != width) || (size.cy != height) )
921                 {
922                     // needs to scale canvas
923                     SetMapMode(hdcDraw, MM_ANISOTROPIC);
924                     SetWindowExtEx(hdcDraw, size.cx, size.cy, NULL);
925                     SetViewportExtEx(hdcDraw, width, height, NULL);
926                 }
927
928                 onDraw(NULL, hdc, hdcDraw, &posRect, NULL);
929
930                 SetMapMode(hdcDraw, MM_TEXT);
931                 BitBlt(hdc, bounds.left, bounds.top,
932                         width, height,
933                         hdcDraw, 0, 0,
934                         SRCCOPY);
935
936                 SelectObject(hdcDraw, oldBmp);
937                 DeleteObject(hBitmap);
938             }
939             DeleteDC(hdcDraw);
940         }
941     }
942 };
943
944 void VLCPlugin::onPositionChange(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
945 {
946     RECT clipRect = *lprcClipRect;
947
948     //RedrawWindow(GetParent(_inplacewnd), &_posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
949
950     /*
951     ** record keeping of control geometry within container
952     */
953     _posRect = *lprcPosRect;
954
955     /*
956     ** change in-place window geometry to match clipping region
957     */
958     SetWindowPos(_inplacewnd, NULL,
959             lprcPosRect->left,
960             lprcPosRect->top,
961             lprcPosRect->right-lprcPosRect->left,
962             lprcPosRect->bottom-lprcPosRect->top,
963             SWP_NOACTIVATE|
964             SWP_NOCOPYBITS|
965             SWP_NOZORDER|
966             SWP_NOOWNERZORDER );
967
968     /* change cliprect coordinates system relative to window bounding rect */
969     OffsetRect(&clipRect, -lprcPosRect->left, -lprcPosRect->top);
970     HRGN clipRgn = CreateRectRgnIndirect(&clipRect);
971     SetWindowRgn(_inplacewnd, clipRgn, FALSE);
972
973     //RedrawWindow(_videownd, &posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
974 };
975
976 void VLCPlugin::freezeEvents(BOOL freeze)
977 {
978     vlcConnectionPointContainer->freezeEvents(freeze);
979 };
980
981 void VLCPlugin::firePropChangedEvent(DISPID dispid)
982 {
983     vlcConnectionPointContainer->firePropChangedEvent(dispid);
984 };
985
986 void VLCPlugin::fireOnPlayEvent(void)
987 {
988     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
989     vlcConnectionPointContainer->fireEvent(DISPID_PlayEvent, &dispparamsNoArgs);
990 };
991
992 void VLCPlugin::fireOnPauseEvent(void)
993 {
994     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
995     vlcConnectionPointContainer->fireEvent(DISPID_PauseEvent, &dispparamsNoArgs);
996 };
997
998 void VLCPlugin::fireOnStopEvent(void)
999 {
1000     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1001     vlcConnectionPointContainer->fireEvent(DISPID_StopEvent, &dispparamsNoArgs);
1002 };
1003
1004 /*
1005  * Async events
1006  */
1007 void VLCPlugin::fireOnIdleEvent()
1008 {
1009     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1010     vlcConnectionPointContainer->fireEvent(DISPID_NothingSpecialEvent, &dispparamsNoArgs);
1011 };
1012
1013 void VLCPlugin::fireOnOpeningEvent()
1014 {
1015     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1016     vlcConnectionPointContainer->fireEvent(DISPID_OpeningEvent, &dispparamsNoArgs);
1017 };
1018
1019 void VLCPlugin::fireOnBufferingEvent()
1020 {
1021     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1022     vlcConnectionPointContainer->fireEvent(DISPID_BufferingEvent, &dispparamsNoArgs);
1023 };
1024
1025 void VLCPlugin::fireOnPlayingEvent()
1026 {
1027     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1028     vlcConnectionPointContainer->fireEvent(DISPID_PlayingEvent, &dispparamsNoArgs);
1029 };
1030
1031 void VLCPlugin::fireOnPausedEvent()
1032 {
1033     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1034     vlcConnectionPointContainer->fireEvent(DISPID_PausedEvent, &dispparamsNoArgs);
1035 };
1036
1037 void VLCPlugin::fireOnErrorEvent()
1038 {
1039     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1040     vlcConnectionPointContainer->fireEvent(DISPID_EncounteredErrorEvent, &dispparamsNoArgs);
1041 };
1042
1043 void VLCPlugin::fireOnEndedEvent()
1044 {
1045     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1046     vlcConnectionPointContainer->fireEvent(DISPID_EndReachedEvent, &dispparamsNoArgs);
1047 };
1048
1049 void VLCPlugin::fireOnStoppedEvent()
1050 {
1051     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1052     vlcConnectionPointContainer->fireEvent(DISPID_StoppedEvent, &dispparamsNoArgs);
1053 };
1054
1055 void VLCPlugin::fireOnForwardEvent()
1056 {
1057     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1058     vlcConnectionPointContainer->fireEvent(DISPID_ForwardEvent, &dispparamsNoArgs);
1059 };
1060
1061 void VLCPlugin::fireOnBackwardEvent()
1062 {
1063     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1064     vlcConnectionPointContainer->fireEvent(DISPID_BackwardEvent, &dispparamsNoArgs);
1065 };
1066
1067 static void handle_input_state_event(const libvlc_event_t* event, void *param)
1068 {
1069     VLCPlugin *plugin = (VLCPlugin*)param;
1070     switch( event->type )
1071     {
1072         case libvlc_MediaPlayerNothingSpecial:
1073             plugin->fireOnIdleEvent();
1074             break;
1075         case libvlc_MediaPlayerOpening:
1076             plugin->fireOnOpeningEvent();
1077             break;
1078         case libvlc_MediaPlayerBuffering:
1079             plugin->fireOnBufferingEvent();
1080             break;
1081         case libvlc_MediaPlayerPlaying:
1082             plugin->fireOnPlayingEvent();
1083             break;
1084         case libvlc_MediaPlayerPaused:
1085             plugin->fireOnPausedEvent();
1086             break;
1087         case libvlc_MediaPlayerStopped:
1088             plugin->fireOnStoppedEvent();
1089             break;
1090         case libvlc_MediaPlayerForward:
1091             plugin->fireOnForwardEvent();
1092             break;
1093         case libvlc_MediaPlayerBackward:
1094             plugin->fireOnBackwardEvent();
1095             break;
1096         case libvlc_MediaPlayerEndReached:
1097             plugin->fireOnEndedEvent();
1098             break;
1099         case libvlc_MediaPlayerEncounteredError:
1100             plugin->fireOnErrorEvent();
1101             break;
1102     }
1103 }
1104
1105 void VLCPlugin::fireOnTimeChangedEvent(long time)
1106 {
1107     VARIANT varPos;
1108     DISPPARAMS params = { &varPos, NULL, 1, 0 };
1109     varPos.vt = VT_I4;
1110     varPos.lVal = time;
1111     vlcConnectionPointContainer->fireEvent(DISPID_TimeChangedEvent, &params);
1112 };
1113
1114 static void handle_time_changed_event(const libvlc_event_t* event, void *param)
1115 {
1116     VLCPlugin *plugin = (VLCPlugin*)param;
1117     plugin->fireOnTimeChangedEvent(event->u.media_player_time_changed.new_time);
1118 }
1119
1120 void VLCPlugin::fireOnPositionChangedEvent(long position)
1121 {
1122     VARIANT varPos;
1123     DISPPARAMS params = { &varPos, NULL, 1, 0 };
1124     varPos.vt = VT_I4;
1125     varPos.lVal = position;
1126     vlcConnectionPointContainer->fireEvent(DISPID_PositionChangedEvent, &params);
1127 };
1128
1129 static void handle_position_changed_event(const libvlc_event_t* event, void *param)
1130 {
1131     VLCPlugin *plugin = (VLCPlugin*)param;
1132     plugin->fireOnPositionChangedEvent(event->u.media_player_position_changed.new_position);
1133 }
1134
1135 void VLCPlugin::fireOnSeekableChangedEvent(VARIANT_BOOL seekable)
1136 {
1137     VARIANT varSeek;
1138     DISPPARAMS params = { &varSeek, NULL, 1, 0 };
1139     varSeek.vt = VT_BOOL;
1140     varSeek.boolVal = seekable;
1141     vlcConnectionPointContainer->fireEvent(DISPID_SeekableChangedEvent, &params);
1142 };
1143
1144 static void handle_seekable_changed_event(const libvlc_event_t* event, void *param)
1145 {
1146     VLCPlugin *plugin = (VLCPlugin*)param;
1147     plugin->fireOnSeekableChangedEvent(event->u.media_player_seekable_changed.new_seekable);
1148 }
1149
1150 void VLCPlugin::fireOnPausableChangedEvent(VARIANT_BOOL pausable)
1151 {
1152     VARIANT varPause;
1153     DISPPARAMS params = { &varPause, NULL, 1, 0 };
1154     varPause.vt = VT_BOOL;
1155     varPause.boolVal = pausable;
1156     vlcConnectionPointContainer->fireEvent(DISPID_PausableChangedEvent, &params);
1157 };
1158
1159 static void handle_pausable_changed_event(const libvlc_event_t* event, void *param)
1160 {
1161     VLCPlugin *plugin = (VLCPlugin*)param;
1162     plugin->fireOnPausableChangedEvent(event->u.media_player_pausable_changed.new_pausable);
1163 }
1164
1165 /* mouse events */
1166 void VLCPlugin::fireOnMouseButtonEvent(VARIANT_BOOL btn_right, VARIANT_BOOL btn_center,
1167                 VARIANT_BOOL btn_left, VARIANT_BOOL btn_wheel_up,
1168                 VARIANT_BOOL btn_wheel_down)
1169 {
1170     VARIANT varButton[5];
1171     DISPPARAMS params = { varButton, NULL, 5, 0 };
1172     varButton[0].vt = VT_BOOL;
1173     varButton[0].boolVal = btn_right;
1174     varButton[1].vt = VT_BOOL;
1175     varButton[1].boolVal = btn_center;
1176     varButton[2].vt = VT_BOOL;
1177     varButton[2].boolVal = btn_left;
1178     varButton[3].vt = VT_BOOL;
1179     varButton[3].boolVal = btn_wheel_up;
1180     varButton[4].vt = VT_BOOL;
1181     varButton[4].boolVal = btn_wheel_down;
1182     vlcConnectionPointContainer->fireEvent(DISPID_MouseButtonEvent, &params);
1183 };
1184
1185 void VLCPlugin::fireOnMouseMovedEvent(long x, long y)
1186 {
1187     VARIANT varMoved[2];
1188     DISPPARAMS params = { varMoved, NULL, 3, 0 };
1189     varMoved[0].vt = VT_INT;
1190     varMoved[0].intVal = x;
1191     varMoved[1].vt = VT_INT;
1192     varMoved[1].intVal = y;
1193     vlcConnectionPointContainer->fireEvent(DISPID_MouseMovedEvent, &params);
1194 };
1195
1196 void VLCPlugin::fireOnMouseClickedEvent(VARIANT_BOOL clicked)
1197 {
1198     VARIANT varClicked;
1199     DISPPARAMS params = { &varClicked, NULL, 1, 0 };
1200     varClicked.vt = VT_BOOL;
1201     varClicked.boolVal = clicked;
1202     vlcConnectionPointContainer->fireEvent(DISPID_MouseClickedEvent, &params);
1203 };
1204
1205 void VLCPlugin::fireOnMouseObjectEvent(VARIANT_BOOL moved)
1206 {
1207     VARIANT varMoved;
1208     DISPPARAMS params = { &varMoved, NULL, 1, 0 };
1209     varMoved.vt = VT_BOOL;
1210     varMoved.boolVal = moved;
1211     vlcConnectionPointContainer->fireEvent(DISPID_MouseObjectEvent, &params);
1212 };
1213
1214 static void handle_mouse_button_pressed_event(const libvlc_event_t* event, void *param)
1215 {
1216     VLCPlugin *plugin = (VLCPlugin*)param;
1217     VARIANT_BOOL btn_right, btn_center, btn_left, btn_wheel_up, btn_wheel_down;
1218 #define B(val) ((val) ? 0xFFFF : 0x0000)
1219     btn_right = B(event->u.media_player_mouse_button.mb_right);
1220     btn_center = B(event->u.media_player_mouse_button.mb_center);
1221     btn_left = B(event->u.media_player_mouse_button.mb_left);
1222     btn_wheel_up = B(event->u.media_player_mouse_button.mb_wheel_up);
1223     btn_wheel_down = B(event->u.media_player_mouse_button.mb_wheel_down);
1224 #undef B
1225     plugin->fireOnMouseButtonEvent(btn_right, btn_center, btn_left,
1226                                  btn_wheel_up, btn_wheel_down);
1227 }
1228
1229 static void handle_mouse_moved_event(const libvlc_event_t* event, void *param)
1230 {
1231     VLCPlugin *plugin = (VLCPlugin*)param;
1232     plugin->fireOnMouseMovedEvent(event->u.media_player_mouse_moved.x,
1233                                   event->u.media_player_mouse_moved.y);
1234 }
1235
1236 static void handle_mouse_clicked_event(const libvlc_event_t* event, void *param)
1237 {
1238     VLCPlugin *plugin = (VLCPlugin*)param;
1239     plugin->fireOnMouseClickedEvent(event->u.media_player_mouse_clicked.clicked);
1240 }
1241
1242 static void handle_mouse_object_event(const libvlc_event_t* event, void *param)
1243 {
1244     VLCPlugin *plugin = (VLCPlugin*)param;
1245     plugin->fireOnMouseObjectEvent(event->u.media_player_mouse_object.moved);
1246 }
1247
1248 /* */
1249
1250 bool VLCPlugin::playlist_select( int idx )
1251 {
1252     libvlc_media_t *p_m = NULL;
1253
1254     assert(_p_mlist);
1255
1256     libvlc_media_list_lock(_p_mlist);
1257
1258     int count = libvlc_media_list_count(_p_mlist);
1259
1260     if( (idx < 0) || (idx >= count) )
1261         goto bad_unlock;
1262
1263     _i_midx = idx;
1264
1265     p_m = libvlc_media_list_item_at_index(_p_mlist,_i_midx);
1266     libvlc_media_list_unlock(_p_mlist);
1267     if( !p_m )
1268         return false;
1269
1270     if( _p_mplayer )
1271     {
1272         player_unregister_events();
1273         libvlc_media_player_release( _p_mplayer );
1274         _p_mplayer = NULL;
1275     }
1276
1277     _p_mplayer = libvlc_media_player_new_from_media(p_m);
1278     if( _p_mplayer )
1279     {
1280         // initial volume setting
1281         libvlc_audio_set_volume(_p_mplayer, _i_volume);
1282         if( _b_mute )
1283             libvlc_audio_set_mute(_p_mplayer, TRUE);
1284         set_player_window();
1285         player_register_events();
1286     }
1287
1288     libvlc_media_release(p_m);
1289     return _p_mplayer ? true : false;
1290
1291 bad_unlock:
1292     libvlc_media_list_unlock(_p_mlist);
1293     return false;
1294 }
1295
1296 void VLCPlugin::set_player_window()
1297 {
1298     // XXX FIXME no idea if this is correct or not
1299     libvlc_media_player_set_hwnd(_p_mplayer,getInPlaceWindow());
1300 }
1301
1302 void VLCPlugin::player_register_events()
1303 {
1304     libvlc_event_manager_t *eventManager = NULL;
1305     assert(_p_mplayer);
1306
1307     eventManager = libvlc_media_player_event_manager(_p_mplayer);
1308     if(eventManager) {
1309         libvlc_event_attach(eventManager, libvlc_MediaPlayerNothingSpecial,
1310                             handle_input_state_event, this);
1311         libvlc_event_attach(eventManager, libvlc_MediaPlayerOpening,
1312                             handle_input_state_event, this);
1313         libvlc_event_attach(eventManager, libvlc_MediaPlayerBuffering,
1314                             handle_input_state_event, this);
1315         libvlc_event_attach(eventManager, libvlc_MediaPlayerPlaying,
1316                             handle_input_state_event, this);
1317         libvlc_event_attach(eventManager, libvlc_MediaPlayerPaused,
1318                             handle_input_state_event, this);
1319         libvlc_event_attach(eventManager, libvlc_MediaPlayerStopped,
1320                             handle_input_state_event, this);
1321         libvlc_event_attach(eventManager, libvlc_MediaPlayerForward,
1322                             handle_input_state_event, this);
1323         libvlc_event_attach(eventManager, libvlc_MediaPlayerBackward,
1324                             handle_input_state_event, this);
1325         libvlc_event_attach(eventManager, libvlc_MediaPlayerEndReached,
1326                             handle_input_state_event, this);
1327         libvlc_event_attach(eventManager, libvlc_MediaPlayerEncounteredError,
1328                             handle_input_state_event, this);
1329
1330         libvlc_event_attach(eventManager, libvlc_MediaPlayerTimeChanged,
1331                             handle_time_changed_event, this);
1332         libvlc_event_attach(eventManager, libvlc_MediaPlayerPositionChanged,
1333                             handle_position_changed_event, this);
1334         libvlc_event_attach(eventManager, libvlc_MediaPlayerSeekableChanged,
1335                             handle_seekable_changed_event, this);
1336         libvlc_event_attach(eventManager, libvlc_MediaPlayerPausableChanged,
1337                             handle_pausable_changed_event, this);
1338
1339         libvlc_event_attach(eventManager, libvlc_MediaPlayerMouseButton,
1340                             handle_mouse_button_pressed_event, this);
1341         libvlc_event_attach(eventManager, libvlc_MediaPlayerMouseMoved,
1342                             handle_mouse_moved_event, this);
1343         libvlc_event_attach(eventManager, libvlc_MediaPlayerMouseClick,
1344                             handle_mouse_clicked_event, this);
1345         libvlc_event_attach(eventManager, libvlc_MediaPlayerMouseObject,
1346                             handle_mouse_object_event, this);
1347     }
1348 }
1349
1350 void VLCPlugin::player_unregister_events()
1351 {
1352     libvlc_event_manager_t *eventManager = NULL;
1353     assert(_p_mplayer);
1354
1355     eventManager = libvlc_media_player_event_manager(_p_mplayer);
1356     if(eventManager) {
1357         libvlc_event_detach(eventManager, libvlc_MediaPlayerNothingSpecial,
1358                             handle_input_state_event, this);
1359         libvlc_event_detach(eventManager, libvlc_MediaPlayerOpening,
1360                             handle_input_state_event, this);
1361         libvlc_event_detach(eventManager, libvlc_MediaPlayerBuffering,
1362                             handle_input_state_event, this);
1363         libvlc_event_detach(eventManager, libvlc_MediaPlayerPlaying,
1364                             handle_input_state_event, this);
1365         libvlc_event_detach(eventManager, libvlc_MediaPlayerPaused,
1366                             handle_input_state_event, this);
1367         libvlc_event_detach(eventManager, libvlc_MediaPlayerStopped,
1368                             handle_input_state_event, this);
1369         libvlc_event_detach(eventManager, libvlc_MediaPlayerForward,
1370                             handle_input_state_event, this);
1371         libvlc_event_detach(eventManager, libvlc_MediaPlayerBackward,
1372                             handle_input_state_event, this);
1373         libvlc_event_detach(eventManager, libvlc_MediaPlayerEndReached,
1374                             handle_input_state_event, this);
1375         libvlc_event_detach(eventManager, libvlc_MediaPlayerEncounteredError,
1376                             handle_input_state_event, this);
1377
1378         libvlc_event_detach(eventManager, libvlc_MediaPlayerTimeChanged,
1379                             handle_time_changed_event, this);
1380         libvlc_event_detach(eventManager, libvlc_MediaPlayerPositionChanged,
1381                             handle_position_changed_event, this);
1382         libvlc_event_detach(eventManager, libvlc_MediaPlayerSeekableChanged,
1383                             handle_seekable_changed_event, this);
1384         libvlc_event_detach(eventManager, libvlc_MediaPlayerPausableChanged,
1385                             handle_pausable_changed_event, this);
1386
1387         libvlc_event_detach(eventManager, libvlc_MediaPlayerMouseButton,
1388                             handle_mouse_button_pressed_event, this);
1389         libvlc_event_detach(eventManager, libvlc_MediaPlayerMouseMoved,
1390                             handle_mouse_moved_event, this);
1391         libvlc_event_detach(eventManager, libvlc_MediaPlayerMouseClick,
1392                             handle_mouse_clicked_event, this);
1393         libvlc_event_detach(eventManager, libvlc_MediaPlayerMouseObject,
1394                             handle_mouse_object_event, this);
1395     }
1396 }
1397
1398 int  VLCPlugin::playlist_add_extended_untrusted(const char *mrl, int optc, const char **optv)
1399 {
1400     int item = -1;
1401     libvlc_media_t *p_m = libvlc_media_new_location(_p_libvlc,mrl);
1402     if( !p_m )
1403         return -1;
1404
1405     for( int i = 0; i < optc; ++i )
1406         libvlc_media_add_option_flag(p_m, optv[i], libvlc_media_option_unique);
1407
1408     libvlc_media_list_lock(_p_mlist);
1409     if( libvlc_media_list_add_media(_p_mlist,p_m) == 0 )
1410         item = libvlc_media_list_count(_p_mlist)-1;
1411     libvlc_media_list_unlock(_p_mlist);
1412     libvlc_media_release(p_m);
1413
1414     return item;
1415 }