]> git.sesse.net Git - vlc/blob - projects/activex/plugin.cpp
Remove extra braces.
[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     /*
218     ** bump refcount to avoid recursive release from
219     ** following interfaces when releasing this interface
220     */
221     AddRef();
222     p_class->AddRef();
223
224     vlcOleControl = new VLCOleControl(this);
225     vlcOleInPlaceObject = new VLCOleInPlaceObject(this);
226     vlcOleInPlaceActiveObject = new VLCOleInPlaceActiveObject(this);
227     vlcPersistStorage = new VLCPersistStorage(this);
228     vlcPersistStreamInit = new VLCPersistStreamInit(this);
229     vlcPersistPropertyBag = new VLCPersistPropertyBag(this);
230     vlcProvideClassInfo = new VLCProvideClassInfo(this);
231     vlcConnectionPointContainer = new VLCConnectionPointContainer(this);
232     vlcObjectSafety = new VLCObjectSafety(this);
233     vlcControl = new VLCControl(this);
234     vlcControl2 = new VLCControl2(this);
235     vlcViewObject = new VLCViewObject(this);
236     vlcDataObject = new VLCDataObject(this);
237     vlcOleObject = new VLCOleObject(this);
238     vlcSupportErrorInfo = new VLCSupportErrorInfo(this);
239
240     // configure controlling IUnknown interface for implemented interfaces
241     this->pUnkOuter = (NULL != pUnkOuter) ? pUnkOuter : dynamic_cast<LPUNKNOWN>(this);
242
243     // default picure
244     _p_pict = p_class->getInPlacePict();
245
246     // make sure that persistable properties are initialized
247     onInit();
248 };
249
250 VLCPlugin::~VLCPlugin()
251 {
252     delete vlcSupportErrorInfo;
253     delete vlcOleObject;
254     delete vlcDataObject;
255     delete vlcViewObject;
256     delete vlcControl2;
257     delete vlcControl;
258     delete vlcConnectionPointContainer;
259     delete vlcProvideClassInfo;
260     delete vlcPersistPropertyBag;
261     delete vlcPersistStreamInit;
262     delete vlcPersistStorage;
263     delete vlcOleInPlaceActiveObject;
264     delete vlcOleInPlaceObject;
265     delete vlcObjectSafety;
266
267     delete vlcOleControl;
268     if( _p_pict )
269         _p_pict->Release();
270
271     SysFreeString(_bstr_mrl);
272     SysFreeString(_bstr_baseurl);
273
274     if( _p_mplayer )
275     {
276         if( isPlaying() )
277             playlist_stop();
278
279         player_unregister_events();
280         libvlc_media_player_release(_p_mplayer);
281         _p_mplayer=NULL;
282     }
283     if( _p_mlist )   { libvlc_media_list_release(_p_mlist); _p_mlist=NULL; }
284     if( _p_libvlc )  { libvlc_release(_p_libvlc); _p_libvlc=NULL; }
285
286     _p_class->Release();
287     Release();
288 };
289
290 STDMETHODIMP VLCPlugin::QueryInterface(REFIID riid, void **ppv)
291 {
292     if( NULL == ppv )
293         return E_INVALIDARG;
294
295     if( IID_IUnknown == riid )
296         *ppv = reinterpret_cast<LPVOID>(this);
297     else if( IID_IOleObject == riid )
298         *ppv = reinterpret_cast<LPVOID>(vlcOleObject);
299     else if( IID_IOleControl == riid )
300         *ppv = reinterpret_cast<LPVOID>(vlcOleControl);
301     else if( IID_IOleWindow == riid )
302         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceObject);
303     else if( IID_IOleInPlaceObject == riid )
304         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceObject);
305     else if( IID_IOleInPlaceActiveObject == riid )
306         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceActiveObject);
307     else if( IID_IPersist == riid )
308         *ppv = reinterpret_cast<LPVOID>(vlcPersistStreamInit);
309     else if( IID_IPersistStreamInit == riid )
310         *ppv = reinterpret_cast<LPVOID>(vlcPersistStreamInit);
311     else if( IID_IPersistStorage == riid )
312         *ppv = reinterpret_cast<LPVOID>(vlcPersistStorage);
313     else if( IID_IPersistPropertyBag == riid )
314         *ppv = reinterpret_cast<LPVOID>(vlcPersistPropertyBag);
315     else if( IID_IProvideClassInfo == riid )
316         *ppv = reinterpret_cast<LPVOID>(vlcProvideClassInfo);
317     else if( IID_IProvideClassInfo2 == riid )
318         *ppv = reinterpret_cast<LPVOID>(vlcProvideClassInfo);
319     else if( IID_IConnectionPointContainer == riid )
320         *ppv = reinterpret_cast<LPVOID>(vlcConnectionPointContainer);
321     else if( IID_IObjectSafety == riid )
322         *ppv = reinterpret_cast<LPVOID>(vlcObjectSafety);
323     else if( IID_IDispatch == riid )
324         *ppv = (CLSID_VLCPlugin2 == getClassID()) ?
325                 reinterpret_cast<LPVOID>(vlcControl2) :
326                 reinterpret_cast<LPVOID>(vlcControl);
327     else if( IID_IVLCControl == riid )
328         *ppv = reinterpret_cast<LPVOID>(vlcControl);
329     else if( IID_IVLCControl2 == riid )
330         *ppv = reinterpret_cast<LPVOID>(vlcControl2);
331     else if( IID_IViewObject == riid )
332         *ppv = reinterpret_cast<LPVOID>(vlcViewObject);
333     else if( IID_IViewObject2 == riid )
334         *ppv = reinterpret_cast<LPVOID>(vlcViewObject);
335     else if( IID_IDataObject == riid )
336         *ppv = reinterpret_cast<LPVOID>(vlcDataObject);
337     else if( IID_ISupportErrorInfo == riid )
338         *ppv = reinterpret_cast<LPVOID>(vlcSupportErrorInfo);
339     else
340     {
341         *ppv = NULL;
342         return E_NOINTERFACE;
343     }
344     ((LPUNKNOWN)*ppv)->AddRef();
345     return NOERROR;
346 };
347
348 STDMETHODIMP_(ULONG) VLCPlugin::AddRef(void)
349 {
350     return InterlockedIncrement((LONG *)&_i_ref);
351 };
352
353 STDMETHODIMP_(ULONG) VLCPlugin::Release(void)
354 {
355     if( ! InterlockedDecrement((LONG *)&_i_ref) )
356     {
357         delete this;
358         return 0;
359     }
360     return _i_ref;
361 };
362
363 //////////////////////////////////////
364
365 HRESULT VLCPlugin::onInit(void)
366 {
367     if( NULL == _p_libvlc )
368     {
369         // initialize persistable properties
370         _b_autoplay   = TRUE;
371         _b_autoloop   = FALSE;
372         _b_toolbar    = FALSE;
373         _bstr_baseurl = NULL;
374         _bstr_mrl     = NULL;
375         _b_visible    = TRUE;
376         _b_mute       = FALSE;
377         _i_volume     = 50;
378         _i_time       = 0;
379         _i_backcolor  = 0;
380         // set default/preferred size (320x240) pixels in HIMETRIC
381         HDC hDC = CreateDevDC(NULL);
382         _extent.cx = 320;
383         _extent.cy = 240;
384         HimetricFromDP(hDC, (LPPOINT)&_extent, 1);
385         DeleteDC(hDC);
386
387         return S_OK;
388     }
389     return CO_E_ALREADYINITIALIZED;
390 };
391
392 HRESULT VLCPlugin::onLoad(void)
393 {
394     if( SysStringLen(_bstr_baseurl) == 0 )
395     {
396         /*
397         ** try to retreive the base URL using the client site moniker, which for Internet Explorer
398         ** is the URL of the page the plugin is embedded into.
399         */
400         LPOLECLIENTSITE pClientSite;
401         if( SUCCEEDED(vlcOleObject->GetClientSite(&pClientSite)) && (NULL != pClientSite) )
402         {
403             IBindCtx *pBC = 0;
404             if( SUCCEEDED(CreateBindCtx(0, &pBC)) )
405             {
406                 LPMONIKER pContMoniker = NULL;
407                 if( SUCCEEDED(pClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
408                                 OLEWHICHMK_CONTAINER, &pContMoniker)) )
409                 {
410                     LPOLESTR base_url;
411                     if( SUCCEEDED(pContMoniker->GetDisplayName(pBC, NULL, &base_url)) )
412                     {
413                         /*
414                         ** check that the moniker name is a URL
415                         */
416                         if( UrlIsW(base_url, URLIS_URL) )
417                         {
418                             /* copy base URL */
419                             _bstr_baseurl = SysAllocString(base_url);
420                         }
421                         CoTaskMemFree(base_url);
422                     }
423                 }
424             }
425         }
426     }
427     setDirty(FALSE);
428     return S_OK;
429 };
430
431 void VLCPlugin::initVLC()
432 {
433     extern HMODULE DllGetModule();
434
435     /*
436     ** default initialization options
437     */
438     const char *ppsz_argv[32] = { };
439     int   ppsz_argc = 0;
440
441     char p_progpath[MAX_PATH];
442     {
443         TCHAR w_progpath[MAX_PATH];
444         DWORD len = GetModuleFileName(DllGetModule(), w_progpath, MAX_PATH);
445         w_progpath[MAX_PATH-1] = '\0';
446         if( len > 0 )
447         {
448             len = WideCharToMultiByte(CP_UTF8, 0, w_progpath, len, p_progpath,
449                        sizeof(p_progpath)-1, NULL, NULL);
450             if( len > 0 )
451             {
452                 p_progpath[len] = '\0';
453                 ppsz_argv[0] = p_progpath;
454             }
455         }
456     }
457
458     ppsz_argv[ppsz_argc++] = "-vv";
459
460     HKEY h_key;
461     char p_pluginpath[MAX_PATH];
462     if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("Software\\VideoLAN\\VLC"),
463                       0, KEY_READ, &h_key ) == ERROR_SUCCESS )
464     {
465         DWORD i_type, i_data = MAX_PATH;
466         TCHAR w_pluginpath[MAX_PATH];
467         if( RegQueryValueEx( h_key, TEXT("InstallDir"), 0, &i_type,
468                              (LPBYTE)w_pluginpath, &i_data ) == ERROR_SUCCESS )
469         {
470             w_pluginpath[MAX_PATH-1] = '\0';
471             if( i_type == REG_SZ )
472             {
473                 if( WideCharToMultiByte(CP_UTF8, 0, w_pluginpath, -1, p_pluginpath,
474                          sizeof(p_pluginpath)-sizeof("\\plugins")+1, NULL, NULL) )
475                 {
476                     strcat( p_pluginpath, "\\plugins" );
477                     ppsz_argv[ppsz_argc++] = "--plugin-path";
478                     ppsz_argv[ppsz_argc++] = p_pluginpath;
479                 }
480             }
481         }
482         RegCloseKey( h_key );
483     }
484
485     // make sure plugin isn't affected with VLC single instance mode
486     ppsz_argv[ppsz_argc++] = "--no-one-instance";
487
488     /* common settings */
489     ppsz_argv[ppsz_argc++] = "-vv";
490     ppsz_argv[ppsz_argc++] = "--no-stats";
491     ppsz_argv[ppsz_argc++] = "--no-media-library";
492     ppsz_argv[ppsz_argc++] = "--intf=dummy";
493     ppsz_argv[ppsz_argc++] = "--no-video-title-show";
494
495
496     // loop mode is a configuration option only
497     if( _b_autoloop )
498         ppsz_argv[ppsz_argc++] = "--loop";
499
500     _p_libvlc = libvlc_new(ppsz_argc, ppsz_argv);
501     if( !_p_libvlc )
502         return;
503
504     _p_mlist = libvlc_media_list_new(_p_libvlc);
505
506     // initial playlist item
507     if( SysStringLen(_bstr_mrl) > 0 )
508     {
509         char *psz_mrl = NULL;
510
511         if( SysStringLen(_bstr_baseurl) > 0 )
512         {
513             /*
514             ** if the MRL a relative URL, we should end up with an absolute URL
515             */
516             LPWSTR abs_url = CombineURL(_bstr_baseurl, _bstr_mrl);
517             if( NULL != abs_url )
518             {
519                 psz_mrl = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url));
520                 CoTaskMemFree(abs_url);
521             }
522             else
523             {
524                 psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl);
525             }
526         }
527         else
528         {
529             /*
530             ** baseURL is empty, assume MRL is absolute
531             */
532             psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl);
533         }
534         if( NULL != psz_mrl )
535         {
536             const char *options[1];
537             int i_options = 0;
538
539             char timeBuffer[32];
540             if( _i_time )
541             {
542                 snprintf(timeBuffer, sizeof(timeBuffer), ":start-time=%d", _i_time);
543                 options[i_options++] = timeBuffer;
544             }
545             // add default target to playlist
546             playlist_add_extended_untrusted(psz_mrl, i_options, options);
547             CoTaskMemFree(psz_mrl);
548         }
549     }
550 };
551
552 void VLCPlugin::setErrorInfo(REFIID riid, const char *description)
553 {
554     vlcSupportErrorInfo->setErrorInfo( getClassID() == CLSID_VLCPlugin2 ?
555         OLESTR("VideoLAN.VLCPlugin.2") : OLESTR("VideoLAN.VLCPlugin.1"),
556         riid, description );
557 };
558
559 HRESULT VLCPlugin::onAmbientChanged(LPUNKNOWN pContainer, DISPID dispID)
560 {
561     VARIANT v;
562     switch( dispID )
563     {
564         case DISPID_AMBIENT_BACKCOLOR:
565             VariantInit(&v);
566             V_VT(&v) = VT_I4;
567             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
568             {
569                 setBackColor(V_I4(&v));
570             }
571             break;
572         case DISPID_AMBIENT_DISPLAYNAME:
573             break;
574         case DISPID_AMBIENT_FONT:
575             break;
576         case DISPID_AMBIENT_FORECOLOR:
577             break;
578         case DISPID_AMBIENT_LOCALEID:
579             break;
580         case DISPID_AMBIENT_MESSAGEREFLECT:
581             break;
582         case DISPID_AMBIENT_SCALEUNITS:
583             break;
584         case DISPID_AMBIENT_TEXTALIGN:
585             break;
586         case DISPID_AMBIENT_USERMODE:
587             VariantInit(&v);
588             V_VT(&v) = VT_BOOL;
589             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
590             {
591                 setUserMode(V_BOOL(&v) != VARIANT_FALSE);
592             }
593             break;
594         case DISPID_AMBIENT_UIDEAD:
595             break;
596         case DISPID_AMBIENT_SHOWGRABHANDLES:
597             break;
598         case DISPID_AMBIENT_SHOWHATCHING:
599             break;
600         case DISPID_AMBIENT_DISPLAYASDEFAULT:
601             break;
602         case DISPID_AMBIENT_SUPPORTSMNEMONICS:
603             break;
604         case DISPID_AMBIENT_AUTOCLIP:
605             break;
606         case DISPID_AMBIENT_APPEARANCE:
607             break;
608         case DISPID_AMBIENT_CODEPAGE:
609             VariantInit(&v);
610             V_VT(&v) = VT_I4;
611             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
612             {
613                 setCodePage(V_I4(&v));
614             }
615             break;
616         case DISPID_AMBIENT_PALETTE:
617             break;
618         case DISPID_AMBIENT_CHARSET:
619             break;
620         case DISPID_AMBIENT_RIGHTTOLEFT:
621             break;
622         case DISPID_AMBIENT_TOPTOBOTTOM:
623             break;
624         case DISPID_UNKNOWN:
625             /*
626             ** multiple property change, look up the ones we are interested in
627             */
628             VariantInit(&v);
629             V_VT(&v) = VT_BOOL;
630             if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_USERMODE, v)) )
631             {
632                 setUserMode(V_BOOL(&v) != VARIANT_FALSE);
633             }
634             VariantInit(&v);
635             V_VT(&v) = VT_I4;
636             if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_CODEPAGE, v)) )
637             {
638                 setCodePage(V_I4(&v));
639             }
640             break;
641     }
642     return S_OK;
643 };
644
645 HRESULT VLCPlugin::onClose(DWORD dwSaveOption)
646 {
647     if( isInPlaceActive() )
648     {
649         onInPlaceDeactivate();
650     }
651     if( isRunning() )
652     {
653         libvlc_instance_t* p_libvlc = _p_libvlc;
654
655         _p_libvlc = NULL;
656         vlcDataObject->onClose();
657
658         if( p_libvlc )
659             libvlc_release(p_libvlc);
660     }
661     return S_OK;
662 };
663
664 BOOL VLCPlugin::isInPlaceActive(void)
665 {
666     return (NULL != _inplacewnd);
667 };
668
669 HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprcPosRect, LPCRECT lprcClipRect)
670 {
671     RECT clipRect = *lprcClipRect;
672
673     /*
674     ** record keeping of control geometry within container
675     */
676     _posRect = *lprcPosRect;
677
678     /*
679     ** Create a window for in place activated control.
680     ** the window geometry matches the control viewport
681     ** within container so that embedded video is always
682     ** properly displayed.
683     */
684     _inplacewnd = CreateWindow(_p_class->getInPlaceWndClassName(),
685             TEXT("VLC Plugin In-Place Window"),
686             WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
687             lprcPosRect->left,
688             lprcPosRect->top,
689             lprcPosRect->right-lprcPosRect->left,
690             lprcPosRect->bottom-lprcPosRect->top,
691             hwndParent,
692             0,
693             _p_class->getHInstance(),
694             NULL
695            );
696
697     if( NULL == _inplacewnd )
698         return E_FAIL;
699
700     SetWindowLongPtr(_inplacewnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
701
702     /* change cliprect coordinates system relative to window bounding rect */
703     OffsetRect(&clipRect, -lprcPosRect->left, -lprcPosRect->top);
704
705     HRGN clipRgn = CreateRectRgnIndirect(&clipRect);
706     SetWindowRgn(_inplacewnd, clipRgn, TRUE);
707
708     if( _b_usermode )
709     {
710         /* will run vlc if not done already */
711         libvlc_instance_t* p_libvlc;
712         HRESULT result = getVLC(&p_libvlc);
713         if( FAILED(result) )
714             return result;
715
716         if( _b_autoplay && playlist_select(0) )
717         {
718             libvlc_media_player_play(_p_mplayer);
719             fireOnPlayEvent();
720         }
721     }
722
723     if( isVisible() )
724         ShowWindow(_inplacewnd, SW_SHOW);
725
726     return S_OK;
727 };
728
729 HRESULT VLCPlugin::onInPlaceDeactivate(void)
730 {
731     if( isPlaying() )
732     {
733         playlist_stop();
734         fireOnStopEvent();
735     }
736
737     DestroyWindow(_inplacewnd);
738     _inplacewnd = NULL;
739
740     return S_OK;
741 };
742
743 void VLCPlugin::setVisible(BOOL fVisible)
744 {
745     if( fVisible != _b_visible )
746     {
747         _b_visible = fVisible;
748         if( isInPlaceActive() )
749         {
750             ShowWindow(_inplacewnd, fVisible ? SW_SHOW : SW_HIDE);
751             if( fVisible )
752                 InvalidateRect(_inplacewnd, NULL, TRUE);
753         }
754         setDirty(TRUE);
755         firePropChangedEvent(DISPID_Visible);
756     }
757 };
758
759 void VLCPlugin::setVolume(int volume)
760 {
761     if( volume < 0 )
762         volume = 0;
763     else if( volume > 200 )
764         volume = 200;
765
766     if( volume != _i_volume )
767     {
768         _i_volume = volume;
769         if( isRunning() )
770         {
771             libvlc_media_player_t *p_md;
772             HRESULT hr = getMD(&p_md);
773             if( SUCCEEDED(hr) )
774                 libvlc_audio_set_volume(p_md, _i_volume);
775         }
776         setDirty(TRUE);
777     }
778 };
779
780 void VLCPlugin::setBackColor(OLE_COLOR backcolor)
781 {
782     if( _i_backcolor != backcolor )
783     {
784         _i_backcolor = backcolor;
785         if( isInPlaceActive() )
786         {
787
788         }
789         setDirty(TRUE);
790     }
791 };
792
793 void VLCPlugin::setTime(int seconds)
794 {
795     if( seconds < 0 )
796         seconds = 0;
797
798     if( seconds != _i_time )
799     {
800         setStartTime(_i_time);
801         if( NULL != _p_mplayer )
802         {
803             libvlc_media_player_set_time(_p_mplayer, _i_time);
804         }
805     }
806 };
807
808 void VLCPlugin::setFocus(BOOL fFocus)
809 {
810     if( fFocus )
811         SetActiveWindow(_inplacewnd);
812 };
813
814 BOOL VLCPlugin::hasFocus(void)
815 {
816     return GetActiveWindow() == _inplacewnd;
817 };
818
819 void VLCPlugin::onDraw(DVTARGETDEVICE * ptd, HDC hicTargetDev,
820         HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds)
821 {
822     if( isVisible() )
823     {
824         long width = lprcBounds->right-lprcBounds->left;
825         long height = lprcBounds->bottom-lprcBounds->top;
826
827         RECT bounds = { lprcBounds->left, lprcBounds->top, lprcBounds->right, lprcBounds->bottom };
828
829         if( isUserMode() )
830         {
831             /* VLC is in user mode, just draw background color */
832             COLORREF colorref = RGB(0, 0, 0);
833             OleTranslateColor(_i_backcolor, (HPALETTE)GetStockObject(DEFAULT_PALETTE), &colorref);
834             if( colorref != RGB(0, 0, 0) )
835             {
836                 /* custom background */
837                 HBRUSH colorbrush = CreateSolidBrush(colorref);
838                 FillRect(hdcDraw, &bounds, colorbrush);
839                 DeleteObject((HANDLE)colorbrush);
840             }
841             else
842             {
843                 /* black background */
844                 FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(BLACK_BRUSH));
845             }
846         }
847         else
848         {
849             /* VLC is in design mode, draw the VLC logo */
850             FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(WHITE_BRUSH));
851
852             LPPICTURE pict = getPicture();
853             if( NULL != pict )
854             {
855                 OLE_XSIZE_HIMETRIC picWidth;
856                 OLE_YSIZE_HIMETRIC picHeight;
857
858                 pict->get_Width(&picWidth);
859                 pict->get_Height(&picHeight);
860
861                 SIZEL picSize = { picWidth, picHeight };
862
863                 if( NULL != hicTargetDev )
864                 {
865                     DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1);
866                 }
867                 else if( NULL != (hicTargetDev = CreateDevDC(ptd)) )
868                 {
869                     DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1);
870                     DeleteDC(hicTargetDev);
871                 }
872
873                 if( picSize.cx > width-4 )
874                     picSize.cx = width-4;
875                 if( picSize.cy > height-4 )
876                     picSize.cy = height-4;
877
878                 LONG dstX = lprcBounds->left+(width-picSize.cx)/2;
879                 LONG dstY = lprcBounds->top+(height-picSize.cy)/2;
880
881                 if( NULL != lprcWBounds )
882                 {
883                     RECT wBounds = { lprcWBounds->left, lprcWBounds->top, lprcWBounds->right, lprcWBounds->bottom };
884                     pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy,
885                             0L, picHeight, picWidth, -picHeight, &wBounds);
886                 }
887                 else
888                     pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy,
889                             0L, picHeight, picWidth, -picHeight, NULL);
890
891                 pict->Release();
892             }
893
894             SelectObject(hdcDraw, GetStockObject(BLACK_BRUSH));
895
896             MoveToEx(hdcDraw, bounds.left, bounds.top, NULL);
897             LineTo(hdcDraw, bounds.left+width-1, bounds.top);
898             LineTo(hdcDraw, bounds.left+width-1, bounds.top+height-1);
899             LineTo(hdcDraw, bounds.left, bounds.top+height-1);
900             LineTo(hdcDraw, bounds.left, bounds.top);
901         }
902     }
903 };
904
905 void VLCPlugin::onPaint(HDC hdc, const RECT &bounds, const RECT &clipRect)
906 {
907     if( isVisible() )
908     {
909         /* if VLC is in design mode, draw control logo */
910         HDC hdcDraw = CreateCompatibleDC(hdc);
911         if( NULL != hdcDraw )
912         {
913             SIZEL size = getExtent();
914             DPFromHimetric(hdc, (LPPOINT)&size, 1);
915             RECTL posRect = { 0, 0, size.cx, size.cy };
916
917             int width = bounds.right-bounds.left;
918             int height = bounds.bottom-bounds.top;
919
920             HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
921             if( NULL != hBitmap )
922             {
923                 HBITMAP oldBmp = (HBITMAP)SelectObject(hdcDraw, hBitmap);
924
925                 if( (size.cx != width) || (size.cy != height) )
926                 {
927                     // needs to scale canvas
928                     SetMapMode(hdcDraw, MM_ANISOTROPIC);
929                     SetWindowExtEx(hdcDraw, size.cx, size.cy, NULL);
930                     SetViewportExtEx(hdcDraw, width, height, NULL);
931                 }
932
933                 onDraw(NULL, hdc, hdcDraw, &posRect, NULL);
934
935                 SetMapMode(hdcDraw, MM_TEXT);
936                 BitBlt(hdc, bounds.left, bounds.top,
937                         width, height,
938                         hdcDraw, 0, 0,
939                         SRCCOPY);
940
941                 SelectObject(hdcDraw, oldBmp);
942                 DeleteObject(hBitmap);
943             }
944             DeleteDC(hdcDraw);
945         }
946     }
947 };
948
949 void VLCPlugin::onPositionChange(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
950 {
951     RECT clipRect = *lprcClipRect;
952
953     //RedrawWindow(GetParent(_inplacewnd), &_posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
954
955     /*
956     ** record keeping of control geometry within container
957     */
958     _posRect = *lprcPosRect;
959
960     /*
961     ** change in-place window geometry to match clipping region
962     */
963     SetWindowPos(_inplacewnd, NULL,
964             lprcPosRect->left,
965             lprcPosRect->top,
966             lprcPosRect->right-lprcPosRect->left,
967             lprcPosRect->bottom-lprcPosRect->top,
968             SWP_NOACTIVATE|
969             SWP_NOCOPYBITS|
970             SWP_NOZORDER|
971             SWP_NOOWNERZORDER );
972
973     /* change cliprect coordinates system relative to window bounding rect */
974     OffsetRect(&clipRect, -lprcPosRect->left, -lprcPosRect->top);
975     HRGN clipRgn = CreateRectRgnIndirect(&clipRect);
976     SetWindowRgn(_inplacewnd, clipRgn, FALSE);
977
978     //RedrawWindow(_videownd, &posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
979 };
980
981 void VLCPlugin::freezeEvents(BOOL freeze)
982 {
983     vlcConnectionPointContainer->freezeEvents(freeze);
984 };
985
986 void VLCPlugin::firePropChangedEvent(DISPID dispid)
987 {
988     vlcConnectionPointContainer->firePropChangedEvent(dispid);
989 };
990
991 void VLCPlugin::fireOnPlayEvent(void)
992 {
993     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
994     vlcConnectionPointContainer->fireEvent(DISPID_PlayEvent, &dispparamsNoArgs);
995 };
996
997 void VLCPlugin::fireOnPauseEvent(void)
998 {
999     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1000     vlcConnectionPointContainer->fireEvent(DISPID_PauseEvent, &dispparamsNoArgs);
1001 };
1002
1003 void VLCPlugin::fireOnStopEvent(void)
1004 {
1005     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1006     vlcConnectionPointContainer->fireEvent(DISPID_StopEvent, &dispparamsNoArgs);
1007 };
1008
1009 /*
1010  * Async events
1011  */
1012 void VLCPlugin::fireOnMediaPlayerNothingSpecialEvent()
1013 {
1014     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1015     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerNothingSpecialEvent, &dispparamsNoArgs);
1016 };
1017
1018 void VLCPlugin::fireOnMediaPlayerOpeningEvent()
1019 {
1020     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1021     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerOpeningEvent, &dispparamsNoArgs);
1022 };
1023
1024 void VLCPlugin::fireOnMediaPlayerBufferingEvent(long cache)
1025 {
1026     DISPPARAMS params;
1027     params.cArgs = 1;
1028     params.rgvarg = (VARIANTARG *) CoTaskMemAlloc(sizeof(VARIANTARG) * params.cArgs) ;
1029     memset(params.rgvarg, 0, sizeof(VARIANTARG) * params.cArgs);
1030     params.rgvarg[0].vt = VT_I4;
1031     params.rgvarg[0].lVal = cache;
1032     params.rgdispidNamedArgs = NULL;
1033     params.cNamedArgs = 0;
1034     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerBufferingEvent, &params);
1035 };
1036
1037 void VLCPlugin::fireOnMediaPlayerPlayingEvent()
1038 {
1039     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1040     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerPlayingEvent, &dispparamsNoArgs);
1041 };
1042
1043 void VLCPlugin::fireOnMediaPlayerPausedEvent()
1044 {
1045     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1046     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerPausedEvent, &dispparamsNoArgs);
1047 };
1048
1049 void VLCPlugin::fireOnMediaPlayerEncounteredErrorEvent()
1050 {
1051     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1052     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerEncounteredErrorEvent, &dispparamsNoArgs);
1053 };
1054
1055 void VLCPlugin::fireOnMediaPlayerEndReachedEvent()
1056 {
1057     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1058     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerEndReachedEvent, &dispparamsNoArgs);
1059 };
1060
1061 void VLCPlugin::fireOnMediaPlayerStoppedEvent()
1062 {
1063     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1064     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerStoppedEvent, &dispparamsNoArgs);
1065 };
1066
1067 void VLCPlugin::fireOnMediaPlayerForwardEvent()
1068 {
1069     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1070     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerForwardEvent, &dispparamsNoArgs);
1071 };
1072
1073 void VLCPlugin::fireOnMediaPlayerBackwardEvent()
1074 {
1075     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1076     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerBackwardEvent, &dispparamsNoArgs);
1077 };
1078
1079 static void handle_input_state_event(const libvlc_event_t* event, void *param)
1080 {
1081     VLCPlugin *plugin = (VLCPlugin*)param;
1082     switch( event->type )
1083     {
1084         case libvlc_MediaPlayerNothingSpecial:
1085             plugin->fireOnMediaPlayerNothingSpecialEvent();
1086             break;
1087         case libvlc_MediaPlayerOpening:
1088             plugin->fireOnMediaPlayerOpeningEvent();
1089             break;
1090         case libvlc_MediaPlayerBuffering:
1091             plugin->fireOnMediaPlayerBufferingEvent(event->u.media_player_buffering.new_cache);
1092             break;
1093         case libvlc_MediaPlayerPlaying:
1094             plugin->fireOnMediaPlayerPlayingEvent();
1095             break;
1096         case libvlc_MediaPlayerPaused:
1097             plugin->fireOnMediaPlayerPausedEvent();
1098             break;
1099         case libvlc_MediaPlayerStopped:
1100             plugin->fireOnMediaPlayerStoppedEvent();
1101             break;
1102         case libvlc_MediaPlayerForward:
1103             plugin->fireOnMediaPlayerForwardEvent();
1104             break;
1105         case libvlc_MediaPlayerBackward:
1106             plugin->fireOnMediaPlayerBackwardEvent();
1107             break;
1108         case libvlc_MediaPlayerEndReached:
1109             plugin->fireOnMediaPlayerEndReachedEvent();
1110             break;
1111         case libvlc_MediaPlayerEncounteredError:
1112             plugin->fireOnMediaPlayerEncounteredErrorEvent();
1113             break;
1114     }
1115 }
1116
1117 void VLCPlugin::fireOnMediaPlayerTimeChangedEvent(long time)
1118 {
1119     DISPPARAMS params;
1120     params.cArgs = 1;
1121     params.rgvarg = (VARIANTARG *) CoTaskMemAlloc(sizeof(VARIANTARG) * params.cArgs) ;
1122     memset(params.rgvarg, 0, sizeof(VARIANTARG) * params.cArgs);
1123     params.rgvarg[0].vt = VT_I4;
1124     params.rgvarg[0].lVal = time;
1125     params.rgdispidNamedArgs = NULL;
1126     params.cNamedArgs = 0;
1127     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerTimeChangedEvent, &params);
1128 };
1129
1130 static void handle_time_changed_event(const libvlc_event_t* event, void *param)
1131 {
1132     VLCPlugin *plugin = (VLCPlugin*)param;
1133     plugin->fireOnMediaPlayerTimeChangedEvent(event->u.media_player_time_changed.new_time);
1134 }
1135
1136 void VLCPlugin::fireOnMediaPlayerPositionChangedEvent(long position)
1137 {
1138     DISPPARAMS params;
1139     params.cArgs = 1;
1140     params.rgvarg = (VARIANTARG *) CoTaskMemAlloc(sizeof(VARIANTARG) * params.cArgs) ;
1141     memset(params.rgvarg, 0, sizeof(VARIANTARG) * params.cArgs);
1142     params.rgvarg[0].vt = VT_I4;
1143     params.rgvarg[0].lVal = position;
1144     params.rgdispidNamedArgs = NULL;
1145     params.cNamedArgs = 0;
1146     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerPositionChangedEvent, &params);
1147 };
1148
1149 static void handle_position_changed_event(const libvlc_event_t* event, void *param)
1150 {
1151     VLCPlugin *plugin = (VLCPlugin*)param;
1152     plugin->fireOnMediaPlayerPositionChangedEvent(event->u.media_player_position_changed.new_position);
1153 }
1154
1155 #define B(val) ((val) ? 0xFFFF : 0x0000)
1156 void VLCPlugin::fireOnMediaPlayerSeekableChangedEvent(VARIANT_BOOL seekable)
1157 {
1158     DISPPARAMS params;
1159     params.cArgs = 1;
1160     params.rgvarg = (VARIANTARG *) CoTaskMemAlloc(sizeof(VARIANTARG) * params.cArgs) ;
1161     memset(params.rgvarg, 0, sizeof(VARIANTARG) * params.cArgs);
1162     params.rgvarg[0].vt = VT_BOOL;
1163     params.rgvarg[0].boolVal = seekable;
1164     params.rgdispidNamedArgs = NULL;
1165     params.cNamedArgs = 0;
1166     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerSeekableChangedEvent, &params);
1167 };
1168
1169 static void handle_seekable_changed_event(const libvlc_event_t* event, void *param)
1170 {
1171     VLCPlugin *plugin = (VLCPlugin*)param;
1172     plugin->fireOnMediaPlayerSeekableChangedEvent(B(event->u.media_player_seekable_changed.new_seekable));
1173 }
1174
1175 void VLCPlugin::fireOnMediaPlayerPausableChangedEvent(VARIANT_BOOL pausable)
1176 {
1177     DISPPARAMS params;
1178     params.cArgs = 1;
1179     params.rgvarg = (VARIANTARG *) CoTaskMemAlloc(sizeof(VARIANTARG) * params.cArgs) ;
1180     memset(params.rgvarg, 0, sizeof(VARIANTARG) * params.cArgs);
1181     params.rgvarg[0].vt = VT_BOOL;
1182     params.rgvarg[0].boolVal = pausable;
1183     params.rgdispidNamedArgs = NULL;
1184     params.cNamedArgs = 0;
1185     vlcConnectionPointContainer->fireEvent(DISPID_MediaPlayerPausableChangedEvent, &params);
1186 };
1187
1188 static void handle_pausable_changed_event(const libvlc_event_t* event, void *param)
1189 {
1190     VLCPlugin *plugin = (VLCPlugin*)param;
1191     plugin->fireOnMediaPlayerPausableChangedEvent(B(event->u.media_player_pausable_changed.new_pausable));
1192 }
1193 #undef B
1194
1195 /* */
1196
1197 bool VLCPlugin::playlist_select( int idx )
1198 {
1199     libvlc_media_t *p_m = NULL;
1200
1201     assert(_p_mlist);
1202
1203     libvlc_media_list_lock(_p_mlist);
1204
1205     int count = libvlc_media_list_count(_p_mlist);
1206
1207     if( (idx < 0) || (idx >= count) )
1208         goto bad_unlock;
1209
1210     _i_midx = idx;
1211
1212     p_m = libvlc_media_list_item_at_index(_p_mlist,_i_midx);
1213     libvlc_media_list_unlock(_p_mlist);
1214     if( !p_m )
1215         return false;
1216
1217     if( _p_mplayer )
1218     {
1219         if( isPlaying() )
1220             playlist_stop();
1221         player_unregister_events();
1222         libvlc_media_player_release( _p_mplayer );
1223         _p_mplayer = NULL;
1224     }
1225
1226     _p_mplayer = libvlc_media_player_new_from_media(p_m);
1227     if( _p_mplayer )
1228     {
1229         // initial volume setting
1230         libvlc_audio_set_volume(_p_mplayer, _i_volume);
1231         if( _b_mute )
1232             libvlc_audio_set_mute(_p_mplayer, TRUE);
1233         set_player_window();
1234         player_register_events();
1235     }
1236
1237     libvlc_media_release(p_m);
1238     return _p_mplayer ? true : false;
1239
1240 bad_unlock:
1241     libvlc_media_list_unlock(_p_mlist);
1242     return false;
1243 }
1244
1245 void VLCPlugin::set_player_window()
1246 {
1247     // XXX FIXME no idea if this is correct or not
1248     libvlc_media_player_set_hwnd(_p_mplayer,getInPlaceWindow());
1249 }
1250
1251 void VLCPlugin::player_register_events()
1252 {
1253     libvlc_event_manager_t *eventManager = NULL;
1254     assert(_p_mplayer);
1255
1256     eventManager = libvlc_media_player_event_manager(_p_mplayer);
1257     if(eventManager) {
1258         libvlc_event_attach(eventManager, libvlc_MediaPlayerNothingSpecial,
1259                             handle_input_state_event, this);
1260         libvlc_event_attach(eventManager, libvlc_MediaPlayerOpening,
1261                             handle_input_state_event, this);
1262         libvlc_event_attach(eventManager, libvlc_MediaPlayerBuffering,
1263                             handle_input_state_event, this);
1264         libvlc_event_attach(eventManager, libvlc_MediaPlayerPlaying,
1265                             handle_input_state_event, this);
1266         libvlc_event_attach(eventManager, libvlc_MediaPlayerPaused,
1267                             handle_input_state_event, this);
1268         libvlc_event_attach(eventManager, libvlc_MediaPlayerStopped,
1269                             handle_input_state_event, this);
1270         libvlc_event_attach(eventManager, libvlc_MediaPlayerForward,
1271                             handle_input_state_event, this);
1272         libvlc_event_attach(eventManager, libvlc_MediaPlayerBackward,
1273                             handle_input_state_event, this);
1274         libvlc_event_attach(eventManager, libvlc_MediaPlayerEndReached,
1275                             handle_input_state_event, this);
1276         libvlc_event_attach(eventManager, libvlc_MediaPlayerEncounteredError,
1277                             handle_input_state_event, this);
1278
1279         libvlc_event_attach(eventManager, libvlc_MediaPlayerTimeChanged,
1280                             handle_time_changed_event, this);
1281         libvlc_event_attach(eventManager, libvlc_MediaPlayerPositionChanged,
1282                             handle_position_changed_event, this);
1283         libvlc_event_attach(eventManager, libvlc_MediaPlayerSeekableChanged,
1284                             handle_seekable_changed_event, this);
1285         libvlc_event_attach(eventManager, libvlc_MediaPlayerPausableChanged,
1286                             handle_pausable_changed_event, this);
1287     }
1288 }
1289
1290 void VLCPlugin::player_unregister_events()
1291 {
1292     libvlc_event_manager_t *eventManager = NULL;
1293     assert(_p_mplayer);
1294
1295     eventManager = libvlc_media_player_event_manager(_p_mplayer);
1296     if(eventManager) {
1297         libvlc_event_detach(eventManager, libvlc_MediaPlayerNothingSpecial,
1298                             handle_input_state_event, this);
1299         libvlc_event_detach(eventManager, libvlc_MediaPlayerOpening,
1300                             handle_input_state_event, this);
1301         libvlc_event_detach(eventManager, libvlc_MediaPlayerBuffering,
1302                             handle_input_state_event, this);
1303         libvlc_event_detach(eventManager, libvlc_MediaPlayerPlaying,
1304                             handle_input_state_event, this);
1305         libvlc_event_detach(eventManager, libvlc_MediaPlayerPaused,
1306                             handle_input_state_event, this);
1307         libvlc_event_detach(eventManager, libvlc_MediaPlayerStopped,
1308                             handle_input_state_event, this);
1309         libvlc_event_detach(eventManager, libvlc_MediaPlayerForward,
1310                             handle_input_state_event, this);
1311         libvlc_event_detach(eventManager, libvlc_MediaPlayerBackward,
1312                             handle_input_state_event, this);
1313         libvlc_event_detach(eventManager, libvlc_MediaPlayerEndReached,
1314                             handle_input_state_event, this);
1315         libvlc_event_detach(eventManager, libvlc_MediaPlayerEncounteredError,
1316                             handle_input_state_event, this);
1317
1318         libvlc_event_detach(eventManager, libvlc_MediaPlayerTimeChanged,
1319                             handle_time_changed_event, this);
1320         libvlc_event_detach(eventManager, libvlc_MediaPlayerPositionChanged,
1321                             handle_position_changed_event, this);
1322         libvlc_event_detach(eventManager, libvlc_MediaPlayerSeekableChanged,
1323                             handle_seekable_changed_event, this);
1324         libvlc_event_detach(eventManager, libvlc_MediaPlayerPausableChanged,
1325                             handle_pausable_changed_event, this);
1326     }
1327 }
1328
1329 int  VLCPlugin::playlist_add_extended_untrusted(const char *mrl, int optc, const char **optv)
1330 {
1331     int item = -1;
1332     libvlc_media_t *p_m = libvlc_media_new_location(_p_libvlc,mrl);
1333     if( !p_m )
1334         return -1;
1335
1336     for( int i = 0; i < optc; ++i )
1337         libvlc_media_add_option_flag(p_m, optv[i], libvlc_media_option_unique);
1338
1339     libvlc_media_list_lock(_p_mlist);
1340     if( libvlc_media_list_add_media(_p_mlist,p_m) == 0 )
1341         item = libvlc_media_list_count(_p_mlist)-1;
1342     libvlc_media_list_unlock(_p_mlist);
1343     libvlc_media_release(p_m);
1344
1345     return item;
1346 }