1 /*****************************************************************************
2 * plugin.cpp: ActiveX control for VLC
3 *****************************************************************************
4 * Copyright (C) 2006-2010 the VideoLAN team
6 * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
7 * Jean-Paul Saman <jpsaman@videolan.org>
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.
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.
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 *****************************************************************************/
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"
55 ////////////////////////////////////////////////////////////////////////
58 static LRESULT CALLBACK VLCInPlaceClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
59 VLCPlugin *p_instance = reinterpret_cast<VLCPlugin *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
69 if( GetUpdateRect(hWnd, &pr, FALSE) )
72 GetClientRect(hWnd, &bounds);
73 BeginPaint(hWnd, &ps);
74 p_instance->onPaint(ps.hdc, bounds, pr);
80 return DefWindowProc(hWnd, uMsg, wParam, lParam);
84 VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance, REFCLSID rclsid) :
85 _p_class_ref(p_class_ref),
86 _hinstance(hInstance),
88 _inplace_picture(NULL)
92 if( ! GetClassInfo(hInstance, getInPlaceWndClassName(), &wClass) )
94 wClass.style = CS_NOCLOSE|CS_DBLCLKS;
95 wClass.lpfnWndProc = VLCInPlaceClassWndProc;
96 wClass.cbClsExtra = 0;
97 wClass.cbWndExtra = 0;
98 wClass.hInstance = hInstance;
100 wClass.hCursor = LoadCursor(NULL, IDC_ARROW);
101 wClass.hbrBackground = NULL;
102 wClass.lpszMenuName = NULL;
103 wClass.lpszClassName = getInPlaceWndClassName();
105 _inplace_wndclass_atom = RegisterClass(&wClass);
109 _inplace_wndclass_atom = 0;
112 HBITMAP hbitmap = (HBITMAP)LoadImage(getHInstance(), MAKEINTRESOURCE(2), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
113 if( NULL != hbitmap )
117 pictDesc.cbSizeofstruct = sizeof(PICTDESC);
118 pictDesc.picType = PICTYPE_BITMAP;
119 pictDesc.bmp.hbitmap = hbitmap;
120 pictDesc.bmp.hpal = NULL;
122 if( FAILED(OleCreatePictureIndirect(&pictDesc, IID_IPicture, TRUE, reinterpret_cast<LPVOID*>(&_inplace_picture))) )
123 _inplace_picture = NULL;
128 VLCPluginClass::~VLCPluginClass()
130 if( 0 != _inplace_wndclass_atom )
131 UnregisterClass(MAKEINTATOM(_inplace_wndclass_atom), _hinstance);
133 if( NULL != _inplace_picture )
134 _inplace_picture->Release();
137 STDMETHODIMP VLCPluginClass::QueryInterface(REFIID riid, void **ppv)
142 if( (IID_IUnknown == riid)
143 || (IID_IClassFactory == riid) )
146 *ppv = reinterpret_cast<LPVOID>(this);
153 return E_NOINTERFACE;
156 STDMETHODIMP_(ULONG) VLCPluginClass::AddRef(void)
158 return InterlockedIncrement(_p_class_ref);
161 STDMETHODIMP_(ULONG) VLCPluginClass::Release(void)
163 ULONG refcount = InterlockedDecrement(_p_class_ref);
172 STDMETHODIMP VLCPluginClass::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppv)
179 if( (NULL != pUnkOuter) && (IID_IUnknown != riid) ) {
180 return CLASS_E_NOAGGREGATION;
183 VLCPlugin *plugin = new VLCPlugin(this, pUnkOuter);
186 HRESULT hr = plugin->QueryInterface(riid, ppv);
187 // the following will destroy the object if QueryInterface() failed
191 return E_OUTOFMEMORY;
194 STDMETHODIMP VLCPluginClass::LockServer(BOOL fLock)
204 ////////////////////////////////////////////////////////////////////////
206 VLCPlugin::VLCPlugin(VLCPluginClass *p_class, LPUNKNOWN pUnkOuter) :
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);
235 // configure controlling IUnknown interface for implemented interfaces
236 this->pUnkOuter = (NULL != pUnkOuter) ? pUnkOuter : dynamic_cast<LPUNKNOWN>(this);
239 _p_pict = p_class->getInPlacePict();
241 // make sure that persistable properties are initialized
245 VLCPlugin::~VLCPlugin()
248 ** bump refcount to avoid recursive release from
249 ** following interfaces when releasing this interface
253 delete vlcSupportErrorInfo;
255 delete vlcDataObject;
256 delete vlcViewObject;
259 delete vlcConnectionPointContainer;
260 delete vlcProvideClassInfo;
261 delete vlcPersistPropertyBag;
262 delete vlcPersistStreamInit;
263 delete vlcPersistStorage;
264 delete vlcOleInPlaceActiveObject;
265 delete vlcOleInPlaceObject;
266 delete vlcObjectSafety;
268 delete vlcOleControl;
272 SysFreeString(_bstr_mrl);
273 SysFreeString(_bstr_baseurl);
277 player_unregister_events();
278 libvlc_media_player_release(_p_mplayer);
281 if( _p_mlist ) { libvlc_media_list_release(_p_mlist); _p_mlist=NULL; }
282 if( _p_libvlc ) { libvlc_release(_p_libvlc); _p_libvlc=NULL; }
287 STDMETHODIMP VLCPlugin::QueryInterface(REFIID riid, void **ppv)
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);
339 return E_NOINTERFACE;
341 ((LPUNKNOWN)*ppv)->AddRef();
345 STDMETHODIMP_(ULONG) VLCPlugin::AddRef(void)
347 return InterlockedIncrement((LONG *)&_i_ref);
350 STDMETHODIMP_(ULONG) VLCPlugin::Release(void)
352 if( ! InterlockedDecrement((LONG *)&_i_ref) )
360 //////////////////////////////////////
362 HRESULT VLCPlugin::onInit(void)
364 if( NULL == _p_libvlc )
366 // initialize persistable properties
370 _bstr_baseurl = NULL;
377 // set default/preferred size (320x240) pixels in HIMETRIC
378 HDC hDC = CreateDevDC(NULL);
381 HimetricFromDP(hDC, (LPPOINT)&_extent, 1);
386 return CO_E_ALREADYINITIALIZED;
389 HRESULT VLCPlugin::onLoad(void)
391 if( SysStringLen(_bstr_baseurl) == 0 )
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.
397 LPOLECLIENTSITE pClientSite;
398 if( SUCCEEDED(vlcOleObject->GetClientSite(&pClientSite)) && (NULL != pClientSite) )
401 if( SUCCEEDED(CreateBindCtx(0, &pBC)) )
403 LPMONIKER pContMoniker = NULL;
404 if( SUCCEEDED(pClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
405 OLEWHICHMK_CONTAINER, &pContMoniker)) )
408 if( SUCCEEDED(pContMoniker->GetDisplayName(pBC, NULL, &base_url)) )
411 ** check that the moniker name is a URL
413 if( UrlIsW(base_url, URLIS_URL) )
416 _bstr_baseurl = SysAllocString(base_url);
418 CoTaskMemFree(base_url);
428 void VLCPlugin::initVLC()
430 extern HMODULE DllGetModule();
433 ** default initialization options
435 const char *ppsz_argv[32] = { };
438 char p_progpath[MAX_PATH];
440 TCHAR w_progpath[MAX_PATH];
441 DWORD len = GetModuleFileName(DllGetModule(), w_progpath, MAX_PATH);
444 len = WideCharToMultiByte(CP_UTF8, 0, w_progpath, len, p_progpath,
445 sizeof(p_progpath)-1, NULL, NULL);
448 p_progpath[len] = '\0';
449 ppsz_argv[0] = p_progpath;
454 ppsz_argv[ppsz_argc++] = "-vv";
457 char p_pluginpath[MAX_PATH];
458 if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("Software\\VideoLAN\\VLC"),
459 0, KEY_READ, &h_key ) == ERROR_SUCCESS )
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 )
466 if( i_type == REG_SZ )
468 if( WideCharToMultiByte(CP_UTF8, 0, w_pluginpath, -1, p_pluginpath,
469 sizeof(p_pluginpath)-sizeof("\\plugins")+1, NULL, NULL) )
471 strcat( p_pluginpath, "\\plugins" );
472 ppsz_argv[ppsz_argc++] = "--plugin-path";
473 ppsz_argv[ppsz_argc++] = p_pluginpath;
477 RegCloseKey( h_key );
480 // make sure plugin isn't affected with VLC single instance mode
481 ppsz_argv[ppsz_argc++] = "--no-one-instance";
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";
491 // loop mode is a configuration option only
493 ppsz_argv[ppsz_argc++] = "--loop";
495 _p_libvlc = libvlc_new(ppsz_argc, ppsz_argv);
499 _p_mlist = libvlc_media_list_new(_p_libvlc);
501 // initial playlist item
502 if( SysStringLen(_bstr_mrl) > 0 )
504 char *psz_mrl = NULL;
506 if( SysStringLen(_bstr_baseurl) > 0 )
509 ** if the MRL a relative URL, we should end up with an absolute URL
511 LPWSTR abs_url = CombineURL(_bstr_baseurl, _bstr_mrl);
512 if( NULL != abs_url )
514 psz_mrl = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url));
515 CoTaskMemFree(abs_url);
519 psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl);
525 ** baseURL is empty, assume MRL is absolute
527 psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl);
529 if( NULL != psz_mrl )
531 const char *options[1];
537 snprintf(timeBuffer, sizeof(timeBuffer), ":start-time=%d", _i_time);
538 options[i_options++] = timeBuffer;
540 // add default target to playlist
541 playlist_add_extended_untrusted(psz_mrl, i_options, options);
542 CoTaskMemFree(psz_mrl);
547 void VLCPlugin::setErrorInfo(REFIID riid, const char *description)
549 vlcSupportErrorInfo->setErrorInfo( getClassID() == CLSID_VLCPlugin2 ?
550 OLESTR("VideoLAN.VLCPlugin.2") : OLESTR("VideoLAN.VLCPlugin.1"),
554 HRESULT VLCPlugin::onAmbientChanged(LPUNKNOWN pContainer, DISPID dispID)
559 case DISPID_AMBIENT_BACKCOLOR:
562 if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
564 setBackColor(V_I4(&v));
567 case DISPID_AMBIENT_DISPLAYNAME:
569 case DISPID_AMBIENT_FONT:
571 case DISPID_AMBIENT_FORECOLOR:
573 case DISPID_AMBIENT_LOCALEID:
575 case DISPID_AMBIENT_MESSAGEREFLECT:
577 case DISPID_AMBIENT_SCALEUNITS:
579 case DISPID_AMBIENT_TEXTALIGN:
581 case DISPID_AMBIENT_USERMODE:
584 if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
586 setUserMode(V_BOOL(&v) != VARIANT_FALSE);
589 case DISPID_AMBIENT_UIDEAD:
591 case DISPID_AMBIENT_SHOWGRABHANDLES:
593 case DISPID_AMBIENT_SHOWHATCHING:
595 case DISPID_AMBIENT_DISPLAYASDEFAULT:
597 case DISPID_AMBIENT_SUPPORTSMNEMONICS:
599 case DISPID_AMBIENT_AUTOCLIP:
601 case DISPID_AMBIENT_APPEARANCE:
603 case DISPID_AMBIENT_CODEPAGE:
606 if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
608 setCodePage(V_I4(&v));
611 case DISPID_AMBIENT_PALETTE:
613 case DISPID_AMBIENT_CHARSET:
615 case DISPID_AMBIENT_RIGHTTOLEFT:
617 case DISPID_AMBIENT_TOPTOBOTTOM:
621 ** multiple property change, look up the ones we are interested in
625 if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_USERMODE, v)) )
627 setUserMode(V_BOOL(&v) != VARIANT_FALSE);
631 if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_CODEPAGE, v)) )
633 setCodePage(V_I4(&v));
640 HRESULT VLCPlugin::onClose(DWORD dwSaveOption)
642 if( isInPlaceActive() )
644 onInPlaceDeactivate();
648 libvlc_instance_t* p_libvlc = _p_libvlc;
651 vlcDataObject->onClose();
654 libvlc_release(p_libvlc);
659 BOOL VLCPlugin::isInPlaceActive(void)
661 return (NULL != _inplacewnd);
664 HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprcPosRect, LPCRECT lprcClipRect)
666 RECT clipRect = *lprcClipRect;
669 ** record keeping of control geometry within container
671 _posRect = *lprcPosRect;
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.
679 _inplacewnd = CreateWindow(_p_class->getInPlaceWndClassName(),
680 TEXT("VLC Plugin In-Place Window"),
681 WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
684 lprcPosRect->right-lprcPosRect->left,
685 lprcPosRect->bottom-lprcPosRect->top,
688 _p_class->getHInstance(),
692 if( NULL == _inplacewnd )
695 SetWindowLongPtr(_inplacewnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
697 /* change cliprect coordinates system relative to window bounding rect */
698 OffsetRect(&clipRect, -lprcPosRect->left, -lprcPosRect->top);
700 HRGN clipRgn = CreateRectRgnIndirect(&clipRect);
701 SetWindowRgn(_inplacewnd, clipRgn, TRUE);
705 /* will run vlc if not done already */
706 libvlc_instance_t* p_libvlc;
707 HRESULT result = getVLC(&p_libvlc);
711 if( _b_autoplay && playlist_select(0) )
713 libvlc_media_player_play(_p_mplayer);
719 ShowWindow(_inplacewnd, SW_SHOW);
724 HRESULT VLCPlugin::onInPlaceDeactivate(void)
732 DestroyWindow(_inplacewnd);
738 void VLCPlugin::setVisible(BOOL fVisible)
740 if( fVisible != _b_visible )
742 _b_visible = fVisible;
743 if( isInPlaceActive() )
745 ShowWindow(_inplacewnd, fVisible ? SW_SHOW : SW_HIDE);
747 InvalidateRect(_inplacewnd, NULL, TRUE);
750 firePropChangedEvent(DISPID_Visible);
754 void VLCPlugin::setVolume(int volume)
758 else if( volume > 200 )
761 if( volume != _i_volume )
766 libvlc_media_player_t *p_md;
767 HRESULT hr = getMD(&p_md);
769 libvlc_audio_set_volume(p_md, _i_volume);
775 void VLCPlugin::setBackColor(OLE_COLOR backcolor)
777 if( _i_backcolor != backcolor )
779 _i_backcolor = backcolor;
780 if( isInPlaceActive() )
788 void VLCPlugin::setTime(int seconds)
793 if( seconds != _i_time )
795 setStartTime(_i_time);
796 if( NULL != _p_mplayer )
798 libvlc_media_player_set_time(_p_mplayer, _i_time);
803 void VLCPlugin::setFocus(BOOL fFocus)
806 SetActiveWindow(_inplacewnd);
809 BOOL VLCPlugin::hasFocus(void)
811 return GetActiveWindow() == _inplacewnd;
814 void VLCPlugin::onDraw(DVTARGETDEVICE * ptd, HDC hicTargetDev,
815 HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds)
819 long width = lprcBounds->right-lprcBounds->left;
820 long height = lprcBounds->bottom-lprcBounds->top;
822 RECT bounds = { lprcBounds->left, lprcBounds->top, lprcBounds->right, lprcBounds->bottom };
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) )
831 /* custom background */
832 HBRUSH colorbrush = CreateSolidBrush(colorref);
833 FillRect(hdcDraw, &bounds, colorbrush);
834 DeleteObject((HANDLE)colorbrush);
838 /* black background */
839 FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(BLACK_BRUSH));
844 /* VLC is in design mode, draw the VLC logo */
845 FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(WHITE_BRUSH));
847 LPPICTURE pict = getPicture();
850 OLE_XSIZE_HIMETRIC picWidth;
851 OLE_YSIZE_HIMETRIC picHeight;
853 pict->get_Width(&picWidth);
854 pict->get_Height(&picHeight);
856 SIZEL picSize = { picWidth, picHeight };
858 if( NULL != hicTargetDev )
860 DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1);
862 else if( NULL != (hicTargetDev = CreateDevDC(ptd)) )
864 DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1);
865 DeleteDC(hicTargetDev);
868 if( picSize.cx > width-4 )
869 picSize.cx = width-4;
870 if( picSize.cy > height-4 )
871 picSize.cy = height-4;
873 LONG dstX = lprcBounds->left+(width-picSize.cx)/2;
874 LONG dstY = lprcBounds->top+(height-picSize.cy)/2;
876 if( NULL != lprcWBounds )
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);
883 pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy,
884 0L, picHeight, picWidth, -picHeight, NULL);
889 SelectObject(hdcDraw, GetStockObject(BLACK_BRUSH));
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);
900 void VLCPlugin::onPaint(HDC hdc, const RECT &bounds, const RECT &clipRect)
904 /* if VLC is in design mode, draw control logo */
905 HDC hdcDraw = CreateCompatibleDC(hdc);
906 if( NULL != hdcDraw )
908 SIZEL size = getExtent();
909 DPFromHimetric(hdc, (LPPOINT)&size, 1);
910 RECTL posRect = { 0, 0, size.cx, size.cy };
912 int width = bounds.right-bounds.left;
913 int height = bounds.bottom-bounds.top;
915 HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
916 if( NULL != hBitmap )
918 HBITMAP oldBmp = (HBITMAP)SelectObject(hdcDraw, hBitmap);
920 if( (size.cx != width) || (size.cy != height) )
922 // needs to scale canvas
923 SetMapMode(hdcDraw, MM_ANISOTROPIC);
924 SetWindowExtEx(hdcDraw, size.cx, size.cy, NULL);
925 SetViewportExtEx(hdcDraw, width, height, NULL);
928 onDraw(NULL, hdc, hdcDraw, &posRect, NULL);
930 SetMapMode(hdcDraw, MM_TEXT);
931 BitBlt(hdc, bounds.left, bounds.top,
936 SelectObject(hdcDraw, oldBmp);
937 DeleteObject(hBitmap);
944 void VLCPlugin::onPositionChange(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
946 RECT clipRect = *lprcClipRect;
948 //RedrawWindow(GetParent(_inplacewnd), &_posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
951 ** record keeping of control geometry within container
953 _posRect = *lprcPosRect;
956 ** change in-place window geometry to match clipping region
958 SetWindowPos(_inplacewnd, NULL,
961 lprcPosRect->right-lprcPosRect->left,
962 lprcPosRect->bottom-lprcPosRect->top,
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);
973 //RedrawWindow(_videownd, &posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
976 void VLCPlugin::freezeEvents(BOOL freeze)
978 vlcConnectionPointContainer->freezeEvents(freeze);
981 void VLCPlugin::firePropChangedEvent(DISPID dispid)
983 vlcConnectionPointContainer->firePropChangedEvent(dispid);
986 void VLCPlugin::fireOnPlayEvent(void)
988 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
989 vlcConnectionPointContainer->fireEvent(DISPID_PlayEvent, &dispparamsNoArgs);
992 void VLCPlugin::fireOnPauseEvent(void)
994 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
995 vlcConnectionPointContainer->fireEvent(DISPID_PauseEvent, &dispparamsNoArgs);
998 void VLCPlugin::fireOnStopEvent(void)
1000 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1001 vlcConnectionPointContainer->fireEvent(DISPID_StopEvent, &dispparamsNoArgs);
1007 void VLCPlugin::fireOnIdleEvent()
1009 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1010 vlcConnectionPointContainer->fireEvent(DISPID_NothingSpecialEvent, &dispparamsNoArgs);
1013 void VLCPlugin::fireOnOpeningEvent()
1015 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1016 vlcConnectionPointContainer->fireEvent(DISPID_OpeningEvent, &dispparamsNoArgs);
1019 void VLCPlugin::fireOnBufferingEvent()
1021 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1022 vlcConnectionPointContainer->fireEvent(DISPID_BufferingEvent, &dispparamsNoArgs);
1025 void VLCPlugin::fireOnPlayingEvent()
1027 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1028 vlcConnectionPointContainer->fireEvent(DISPID_PlayingEvent, &dispparamsNoArgs);
1031 void VLCPlugin::fireOnPausedEvent()
1033 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1034 vlcConnectionPointContainer->fireEvent(DISPID_PausedEvent, &dispparamsNoArgs);
1037 void VLCPlugin::fireOnErrorEvent()
1039 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1040 vlcConnectionPointContainer->fireEvent(DISPID_EncounteredErrorEvent, &dispparamsNoArgs);
1043 void VLCPlugin::fireOnEndedEvent()
1045 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1046 vlcConnectionPointContainer->fireEvent(DISPID_EndReachedEvent, &dispparamsNoArgs);
1049 void VLCPlugin::fireOnStoppedEvent()
1051 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1052 vlcConnectionPointContainer->fireEvent(DISPID_StoppedEvent, &dispparamsNoArgs);
1055 void VLCPlugin::fireOnForwardEvent()
1057 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1058 vlcConnectionPointContainer->fireEvent(DISPID_ForwardEvent, &dispparamsNoArgs);
1061 void VLCPlugin::fireOnBackwardEvent()
1063 DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
1064 vlcConnectionPointContainer->fireEvent(DISPID_BackwardEvent, &dispparamsNoArgs);
1067 static void handle_input_state_event(const libvlc_event_t* event, void *param)
1069 VLCPlugin *plugin = (VLCPlugin*)param;
1070 switch( event->type )
1072 case libvlc_MediaPlayerNothingSpecial:
1073 plugin->fireOnIdleEvent();
1075 case libvlc_MediaPlayerOpening:
1076 plugin->fireOnOpeningEvent();
1078 case libvlc_MediaPlayerBuffering:
1079 plugin->fireOnBufferingEvent();
1081 case libvlc_MediaPlayerPlaying:
1082 plugin->fireOnPlayingEvent();
1084 case libvlc_MediaPlayerPaused:
1085 plugin->fireOnPausedEvent();
1087 case libvlc_MediaPlayerStopped:
1088 plugin->fireOnStoppedEvent();
1090 case libvlc_MediaPlayerForward:
1091 plugin->fireOnForwardEvent();
1093 case libvlc_MediaPlayerBackward:
1094 plugin->fireOnBackwardEvent();
1096 case libvlc_MediaPlayerEndReached:
1097 plugin->fireOnEndedEvent();
1099 case libvlc_MediaPlayerEncounteredError:
1100 plugin->fireOnErrorEvent();
1105 void VLCPlugin::fireOnTimeChangedEvent(long time)
1108 DISPPARAMS params = { &varPos, NULL, 1, 0 };
1111 vlcConnectionPointContainer->fireEvent(DISPID_TimeChangedEvent, ¶ms);
1114 static void handle_time_changed_event(const libvlc_event_t* event, void *param)
1116 VLCPlugin *plugin = (VLCPlugin*)param;
1117 plugin->fireOnTimeChangedEvent(event->u.media_player_time_changed.new_time);
1120 void VLCPlugin::fireOnPositionChangedEvent(long position)
1123 DISPPARAMS params = { &varPos, NULL, 1, 0 };
1125 varPos.lVal = position;
1126 vlcConnectionPointContainer->fireEvent(DISPID_PositionChangedEvent, ¶ms);
1129 static void handle_position_changed_event(const libvlc_event_t* event, void *param)
1131 VLCPlugin *plugin = (VLCPlugin*)param;
1132 plugin->fireOnPositionChangedEvent(event->u.media_player_position_changed.new_position);
1135 void VLCPlugin::fireOnSeekableChangedEvent(VARIANT_BOOL seekable)
1138 DISPPARAMS params = { &varSeek, NULL, 1, 0 };
1139 varSeek.vt = VT_BOOL;
1140 varSeek.boolVal = seekable;
1141 vlcConnectionPointContainer->fireEvent(DISPID_SeekableChangedEvent, ¶ms);
1144 static void handle_seekable_changed_event(const libvlc_event_t* event, void *param)
1146 VLCPlugin *plugin = (VLCPlugin*)param;
1147 plugin->fireOnSeekableChangedEvent(event->u.media_player_seekable_changed.new_seekable);
1150 void VLCPlugin::fireOnPausableChangedEvent(VARIANT_BOOL pausable)
1153 DISPPARAMS params = { &varPause, NULL, 1, 0 };
1154 varPause.vt = VT_BOOL;
1155 varPause.boolVal = pausable;
1156 vlcConnectionPointContainer->fireEvent(DISPID_PausableChangedEvent, ¶ms);
1159 static void handle_pausable_changed_event(const libvlc_event_t* event, void *param)
1161 VLCPlugin *plugin = (VLCPlugin*)param;
1162 plugin->fireOnPausableChangedEvent(event->u.media_player_pausable_changed.new_pausable);
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)
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, ¶ms);
1185 void VLCPlugin::fireOnMouseMovedEvent(long x, long y)
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, ¶ms);
1196 void VLCPlugin::fireOnMouseClickedEvent(VARIANT_BOOL clicked)
1199 DISPPARAMS params = { &varClicked, NULL, 1, 0 };
1200 varClicked.vt = VT_BOOL;
1201 varClicked.boolVal = clicked;
1202 vlcConnectionPointContainer->fireEvent(DISPID_MouseClickedEvent, ¶ms);
1205 void VLCPlugin::fireOnMouseObjectEvent(VARIANT_BOOL moved)
1208 DISPPARAMS params = { &varMoved, NULL, 1, 0 };
1209 varMoved.vt = VT_BOOL;
1210 varMoved.boolVal = moved;
1211 vlcConnectionPointContainer->fireEvent(DISPID_MouseObjectEvent, ¶ms);
1214 static void handle_mouse_button_pressed_event(const libvlc_event_t* event, void *param)
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);
1225 plugin->fireOnMouseButtonEvent(btn_right, btn_center, btn_left,
1226 btn_wheel_up, btn_wheel_down);
1229 static void handle_mouse_moved_event(const libvlc_event_t* event, void *param)
1231 VLCPlugin *plugin = (VLCPlugin*)param;
1232 plugin->fireOnMouseMovedEvent(event->u.media_player_mouse_moved.x,
1233 event->u.media_player_mouse_moved.y);
1236 static void handle_mouse_clicked_event(const libvlc_event_t* event, void *param)
1238 VLCPlugin *plugin = (VLCPlugin*)param;
1239 plugin->fireOnMouseClickedEvent(event->u.media_player_mouse_clicked.clicked);
1242 static void handle_mouse_object_event(const libvlc_event_t* event, void *param)
1244 VLCPlugin *plugin = (VLCPlugin*)param;
1245 plugin->fireOnMouseObjectEvent(event->u.media_player_mouse_object.moved);
1250 bool VLCPlugin::playlist_select( int idx )
1252 libvlc_media_t *p_m = NULL;
1256 libvlc_media_list_lock(_p_mlist);
1258 int count = libvlc_media_list_count(_p_mlist);
1260 if( (idx < 0) || (idx >= count) )
1265 p_m = libvlc_media_list_item_at_index(_p_mlist,_i_midx);
1266 libvlc_media_list_unlock(_p_mlist);
1272 player_unregister_events();
1273 libvlc_media_player_release( _p_mplayer );
1277 _p_mplayer = libvlc_media_player_new_from_media(p_m);
1280 // initial volume setting
1281 libvlc_audio_set_volume(_p_mplayer, _i_volume);
1283 libvlc_audio_set_mute(_p_mplayer, TRUE);
1284 set_player_window();
1285 player_register_events();
1288 libvlc_media_release(p_m);
1289 return _p_mplayer ? true : false;
1292 libvlc_media_list_unlock(_p_mlist);
1296 void VLCPlugin::set_player_window()
1298 // XXX FIXME no idea if this is correct or not
1299 libvlc_media_player_set_hwnd(_p_mplayer,getInPlaceWindow());
1302 void VLCPlugin::player_register_events()
1304 libvlc_event_manager_t *eventManager = NULL;
1307 eventManager = libvlc_media_player_event_manager(_p_mplayer);
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);
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);
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);
1350 void VLCPlugin::player_unregister_events()
1352 libvlc_event_manager_t *eventManager = NULL;
1355 eventManager = libvlc_media_player_event_manager(_p_mplayer);
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);
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);
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);
1398 int VLCPlugin::playlist_add_extended_untrusted(const char *mrl, int optc, const char **optv)
1401 libvlc_media_t *p_m = libvlc_media_new_location(_p_libvlc,mrl);
1405 for( int i = 0; i < optc; ++i )
1406 libvlc_media_add_option_flag(p_m, optv[i], libvlc_media_option_unique);
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);