X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=activex%2Fplugin.cpp;h=ca23d48cc840122446e175da43dca74ba970ebae;hb=b8acb755a7459323e2cd9a0b0e5c49a7eac55b0c;hp=0ef6092d43d6eea9a408cbaa3998e84409c6846c;hpb=2cb472dba008f7d877ffe6bae9c5575253365282;p=vlc diff --git a/activex/plugin.cpp b/activex/plugin.cpp index 0ef6092d43..ca23d48cc8 100644 --- a/activex/plugin.cpp +++ b/activex/plugin.cpp @@ -1,7 +1,7 @@ /***************************************************************************** * plugin.cpp: ActiveX control for VLC ***************************************************************************** - * Copyright (C) 2005 the VideoLAN team + * Copyright (C) 2006 the VideoLAN team * * Authors: Damien Fouilleul * @@ -33,8 +33,10 @@ #include "connectioncontainer.h" #include "objectsafety.h" #include "vlccontrol.h" +#include "vlccontrol2.h" #include "viewobject.h" #include "dataobject.h" +#include "supporterrorinfo.h" #include "utils.h" @@ -50,31 +52,7 @@ using namespace std; //////////////////////////////////////////////////////////////////////// //class factory -// {E23FE9C6-778E-49d4-B537-38FCDE4887D8} -//const GUID CLSID_VLCPlugin = -// { 0xe23fe9c6, 0x778e, 0x49d4, { 0xb5, 0x37, 0x38, 0xfc, 0xde, 0x48, 0x87, 0xd8 } }; - static LRESULT CALLBACK VLCInPlaceClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch( uMsg ) - { - case WM_ERASEBKGND: - return 1L; - - case WM_PAINT: - PAINTSTRUCT ps; - if( GetUpdateRect(hWnd, NULL, FALSE) ) - { - BeginPaint(hWnd, &ps); - EndPaint(hWnd, &ps); - } - return 0L; - - default: - return DefWindowProc(hWnd, uMsg, wParam, lParam); - } -}; - -static LRESULT CALLBACK VLCVideoClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { VLCPlugin *p_instance = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); switch( uMsg ) @@ -100,9 +78,10 @@ static LRESULT CALLBACK VLCVideoClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam } }; -VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance) : +VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance, REFCLSID rclsid) : _p_class_ref(p_class_ref), _hinstance(hInstance), + _classid(rclsid), _inplace_picture(NULL) { WNDCLASS wClass; @@ -119,7 +98,7 @@ VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance) : wClass.hbrBackground = NULL; wClass.lpszMenuName = NULL; wClass.lpszClassName = getInPlaceWndClassName(); - + _inplace_wndclass_atom = RegisterClass(&wClass); } else @@ -127,26 +106,6 @@ VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance) : _inplace_wndclass_atom = 0; } - if( ! GetClassInfo(hInstance, getVideoWndClassName(), &wClass) ) - { - wClass.style = CS_NOCLOSE; - wClass.lpfnWndProc = VLCVideoClassWndProc; - wClass.cbClsExtra = 0; - wClass.cbWndExtra = 0; - wClass.hInstance = hInstance; - wClass.hIcon = NULL; - wClass.hCursor = LoadCursor(NULL, IDC_ARROW); - wClass.hbrBackground = NULL; - wClass.lpszMenuName = NULL; - wClass.lpszClassName = getVideoWndClassName(); - - _video_wndclass_atom = RegisterClass(&wClass); - } - else - { - _video_wndclass_atom = 0; - } - HBITMAP hbitmap = (HBITMAP)LoadImage(getHInstance(), TEXT("INPLACE-PICT"), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); if( NULL != hbitmap ) { @@ -168,9 +127,6 @@ VLCPluginClass::~VLCPluginClass() if( 0 != _inplace_wndclass_atom ) UnregisterClass(MAKEINTATOM(_inplace_wndclass_atom), _hinstance); - if( 0 != _video_wndclass_atom ) - UnregisterClass(MAKEINTATOM(_video_wndclass_atom), _hinstance); - if( NULL != _inplace_picture ) _inplace_picture->Release(); }; @@ -180,7 +136,8 @@ STDMETHODIMP VLCPluginClass::QueryInterface(REFIID riid, void **ppv) if( NULL == ppv ) return E_INVALIDARG; - if( (IID_IUnknown == riid) || (IID_IClassFactory == riid) ) + if( (IID_IUnknown == riid) + || (IID_IClassFactory == riid) ) { AddRef(); *ppv = reinterpret_cast(this); @@ -224,6 +181,7 @@ STDMETHODIMP VLCPluginClass::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, vo if( NULL != plugin ) { HRESULT hr = plugin->QueryInterface(riid, ppv); + // the following will destroy the object if QueryInterface() failed plugin->Release(); return hr; } @@ -234,7 +192,7 @@ STDMETHODIMP VLCPluginClass::LockServer(BOOL fLock) { if( fLock ) AddRef(); - else + else Release(); return S_OK; @@ -246,14 +204,9 @@ VLCPlugin::VLCPlugin(VLCPluginClass *p_class, LPUNKNOWN pUnkOuter) : _inplacewnd(NULL), _p_class(p_class), _i_ref(1UL), + _p_libvlc(NULL), _i_codepage(CP_ACP), - _b_usermode(TRUE), - _bstr_mrl(NULL), - _b_autoplay(TRUE), - _b_autoloop(FALSE), - _b_visible(TRUE), - _b_mute(FALSE), - _i_vlc(0) + _b_usermode(TRUE) { p_class->AddRef(); @@ -267,9 +220,11 @@ VLCPlugin::VLCPlugin(VLCPluginClass *p_class, LPUNKNOWN pUnkOuter) : vlcConnectionPointContainer = new VLCConnectionPointContainer(this); vlcObjectSafety = new VLCObjectSafety(this); vlcControl = new VLCControl(this); + vlcControl2 = new VLCControl2(this); vlcViewObject = new VLCViewObject(this); vlcDataObject = new VLCDataObject(this); vlcOleObject = new VLCOleObject(this); + vlcSupportErrorInfo = new VLCSupportErrorInfo(this); // configure controlling IUnknown interface for implemented interfaces this->pUnkOuter = (NULL != pUnkOuter) ? pUnkOuter : dynamic_cast(this); @@ -277,19 +232,23 @@ VLCPlugin::VLCPlugin(VLCPluginClass *p_class, LPUNKNOWN pUnkOuter) : // default picure _p_pict = p_class->getInPlacePict(); - // set default/preferred size (320x240) pixels in HIMETRIC - HDC hDC = CreateDevDC(NULL); - _extent.cx = 320; - _extent.cy = 240; - HimetricFromDP(hDC, (LPPOINT)&_extent, 1); - DeleteDC(hDC); + // make sure that persistable properties are initialized + onInit(); }; VLCPlugin::~VLCPlugin() { + /* + ** bump refcount to avoid recursive release from + ** following interfaces when releasing this interface + */ + AddRef(); + + delete vlcSupportErrorInfo; delete vlcOleObject; delete vlcDataObject; delete vlcViewObject; + delete vlcControl2; delete vlcControl; delete vlcConnectionPointContainer; delete vlcProvideClassInfo; @@ -305,6 +264,7 @@ VLCPlugin::~VLCPlugin() _p_pict->Release(); SysFreeString(_bstr_mrl); + SysFreeString(_bstr_baseurl); _p_class->Release(); }; @@ -343,15 +303,21 @@ STDMETHODIMP VLCPlugin::QueryInterface(REFIID riid, void **ppv) else if( IID_IObjectSafety == riid ) *ppv = reinterpret_cast(vlcObjectSafety); else if( IID_IDispatch == riid ) - *ppv = reinterpret_cast(vlcControl); + *ppv = (CLSID_VLCPlugin2 == getClassID()) ? + reinterpret_cast(vlcControl2) : + reinterpret_cast(vlcControl); else if( IID_IVLCControl == riid ) *ppv = reinterpret_cast(vlcControl); + else if( IID_IVLCControl2 == riid ) + *ppv = reinterpret_cast(vlcControl2); else if( IID_IViewObject == riid ) *ppv = reinterpret_cast(vlcViewObject); else if( IID_IViewObject2 == riid ) *ppv = reinterpret_cast(vlcViewObject); else if( IID_IDataObject == riid ) *ppv = reinterpret_cast(vlcDataObject); + else if( IID_ISupportErrorInfo == riid ) + *ppv = reinterpret_cast(vlcSupportErrorInfo); else { *ppv = NULL; @@ -378,157 +344,27 @@ STDMETHODIMP_(ULONG) VLCPlugin::Release(void) ////////////////////////////////////// -/* -** we use a window to represent plugin viewport, -** whose geometry is limited by the clipping rectangle -** all drawing within this window must follow must -** follow coordinates system described in lprPosRect -*/ - -static void getViewportCoords(LPRECT lprPosRect, LPRECT lprClipRect) -{ - RECT bounds; - bounds.right = lprPosRect->right-lprPosRect->left; - - if( lprClipRect->left <= lprPosRect->left ) - { - // left side is not clipped out - bounds.left = 0; - - if( lprClipRect->right >= lprPosRect->right ) - { - // right side is not clipped out, no change - } - else if( lprClipRect->right >= lprPosRect->left ) - { - // right side is clipped out - lprPosRect->right = lprClipRect->right; - } - else - { - // outside of clipping rectange, not visible - lprPosRect->right = lprPosRect->left; - } - } - else - { - // left side is clipped out - bounds.left = lprPosRect->left-lprClipRect->left; - bounds.right += bounds.left; - - lprPosRect->left = lprClipRect->left; - if( lprClipRect->right >= lprPosRect->right ) - { - // right side is not clipped out - } - else - { - // right side is clipped out - lprPosRect->right = lprClipRect->right; - } - } - - bounds.bottom = lprPosRect->bottom-lprPosRect->top; - - if( lprClipRect->top <= lprPosRect->top ) - { - // top side is not clipped out - bounds.top = 0; - - if( lprClipRect->bottom >= lprPosRect->bottom ) - { - // bottom side is not clipped out, no change - } - else if( lprClipRect->bottom >= lprPosRect->top ) - { - // bottom side is clipped out - lprPosRect->bottom = lprClipRect->bottom; - } - else - { - // outside of clipping rectange, not visible - lprPosRect->right = lprPosRect->left; - } - } - else - { - bounds.top = lprPosRect->top-lprClipRect->top; - bounds.bottom += bounds.top; - - lprPosRect->top = lprClipRect->top; - if( lprClipRect->bottom >= lprPosRect->bottom ) - { - // bottom side is not clipped out - } - else - { - // bottom side is clipped out - lprPosRect->bottom = lprClipRect->bottom; - } - } - *lprClipRect = *lprPosRect; - *lprPosRect = bounds; -}; - HRESULT VLCPlugin::onInit(void) { - if( 0 == _i_vlc ) + if( NULL == _p_libvlc ) { - _i_vlc = VLC_Create(); - if( _i_vlc < 0 ) - { - _i_vlc = 0; - return E_FAIL; - } + // initialize persistable properties + _b_autoplay = TRUE; + _b_autoloop = FALSE; + _bstr_baseurl = NULL; + _bstr_mrl = NULL; + _b_visible = TRUE; + _b_mute = FALSE; + _i_volume = 50; + _i_time = 0; + _i_backcolor = 0; + // set default/preferred size (320x240) pixels in HIMETRIC + HDC hDC = CreateDevDC(NULL); + _extent.cx = 320; + _extent.cy = 240; + HimetricFromDP(hDC, (LPPOINT)&_extent, 1); + DeleteDC(hDC); - /* - ** default initialization options - */ - char *ppsz_argv[10] = { "vlc", "-vv" }; - int ppsz_argc = 2; - - HKEY h_key; - DWORD i_type, i_data = MAX_PATH + 1; - char p_data[MAX_PATH + 1]; - if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\VideoLAN\\VLC", - 0, KEY_READ, &h_key ) == ERROR_SUCCESS ) - { - if( RegQueryValueEx( h_key, "InstallDir", 0, &i_type, - (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS ) - { - if( i_type == REG_SZ ) - { - strcat( p_data, "\\vlc" ); - ppsz_argv[0] = p_data; - } - } - RegCloseKey( h_key ); - } - -#if 0 - ppsz_argv[0] = "C:\\cygwin\\home\\Damien_Fouilleul\\dev\\videolan\\vlc-trunk\\vlc"; -#endif - - if( IsDebuggerPresent() ) - { - /* - ** VLC default threading mechanism is designed to be as compatible - ** with POSIX as possible, however when debugged on win32, threads - ** lose signals and eventually VLC get stuck during initialization. - ** threading support can be configured to be more debugging friendly - ** but it will be less compatible with POSIX. - ** This is done by initializing with the following options - */ - ppsz_argv[ppsz_argc++] = "--fast-mutex"; - ppsz_argv[ppsz_argc++] = "--win9x-cv-method=1"; - } - - if( VLC_Init(_i_vlc, ppsz_argc, ppsz_argv) ) - { - VLC_Destroy(_i_vlc); - _i_vlc = 0; - return E_FAIL; - } return S_OK; } return CO_E_ALREADYINITIALIZED; @@ -536,17 +372,13 @@ HRESULT VLCPlugin::onInit(void) HRESULT VLCPlugin::onLoad(void) { - if( _b_mute ) - VLC_VolumeMute(_i_vlc); - - if( SysStringLen(_bstr_mrl) > 0 ) + if( SysStringLen(_bstr_baseurl) == 0 ) { /* - ** try to combine MRL with client site moniker, which for Internet Explorer - ** is the URL of the page the plugin is embedded into. Hence, if the MRL - ** is a relative URL, we should end up with an absolute URL + ** try to retreive the base URL using the client site moniker, which for Internet Explorer + ** is the URL of the page the plugin is embedded into. */ - IOleClientSite *pClientSite; + LPOLECLIENTSITE pClientSite; if( SUCCEEDED(vlcOleObject->GetClientSite(&pClientSite)) && (NULL != pClientSite) ) { IBindCtx *pBC = 0; @@ -564,53 +396,182 @@ HRESULT VLCPlugin::onLoad(void) */ if( UrlIsW(base_url, URLIS_URL) ) { - DWORD len = INTERNET_MAX_URL_LENGTH; - LPOLESTR abs_url = (LPOLESTR)CoTaskMemAlloc(sizeof(OLECHAR)*len); - if( NULL != abs_url ) - { - if( SUCCEEDED(UrlCombineW(base_url, _bstr_mrl, abs_url, &len, - URL_ESCAPE_UNSAFE|URL_PLUGGABLE_PROTOCOL)) ) - { - SysFreeString(_bstr_mrl); - _bstr_mrl = SysAllocStringLen(abs_url, len); - } - CoTaskMemFree(abs_url); - } + /* copy base URL */ + _bstr_baseurl = SysAllocString(base_url); } CoTaskMemFree(base_url); } - pContMoniker->Release(); } - pBC->Release(); } - pClientSite->Release(); + } + } + setDirty(FALSE); + return S_OK; +}; + +HRESULT VLCPlugin::getVLCObject(int* i_vlc) +{ + libvlc_instance_t *p_libvlc; + HRESULT result = getVLC(&p_libvlc); + if( SUCCEEDED(result) ) + { + *i_vlc = libvlc_get_vlc_id(p_libvlc); + } + else + { + *i_vlc = 0; + } + return result; +} + +HRESULT VLCPlugin::getVLC(libvlc_instance_t** pp_libvlc) +{ + extern HMODULE DllGetModule(); + + if( ! isRunning() ) + { + /* + ** default initialization options + */ + char *ppsz_argv[32] = { "vlc" }; + int ppsz_argc = 1; + + char p_progpath[MAX_PATH]; + { + TCHAR w_progpath[MAX_PATH]; + DWORD len = GetModuleFileName(DllGetModule(), w_progpath, MAX_PATH); + if( len > 0 ) + { + len = WideCharToMultiByte(CP_UTF8, 0, w_progpath, len, p_progpath, + sizeof(p_progpath)-1, NULL, NULL); + if( len > 0 ) + { + p_progpath[len] = '\0'; + ppsz_argv[0] = p_progpath; + } + } + } + + ppsz_argv[ppsz_argc++] = "-vv"; + + HKEY h_key; + char p_pluginpath[MAX_PATH]; + if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("Software\\VideoLAN\\VLC"), + 0, KEY_READ, &h_key ) == ERROR_SUCCESS ) + { + DWORD i_type, i_data = MAX_PATH; + TCHAR w_pluginpath[MAX_PATH]; + if( RegQueryValueEx( h_key, TEXT("InstallDir"), 0, &i_type, + (LPBYTE)w_pluginpath, &i_data ) == ERROR_SUCCESS ) + { + if( i_type == REG_SZ ) + { + if( WideCharToMultiByte(CP_UTF8, 0, w_pluginpath, -1, p_pluginpath, + sizeof(p_pluginpath)-sizeof("\\plugins")+1, NULL, NULL) ) + { + strcat( p_pluginpath, "\\plugins" ); + ppsz_argv[ppsz_argc++] = "--plugin-path"; + ppsz_argv[ppsz_argc++] = p_pluginpath; + } + } + } + RegCloseKey( h_key ); + } + + // make sure plugin isn't affected with VLC single instance mode + ppsz_argv[ppsz_argc++] = "--no-one-instance"; + + /* common settings */ + ppsz_argv[ppsz_argc++] = "--no-stats"; + ppsz_argv[ppsz_argc++] = "--no-media-library"; + ppsz_argv[ppsz_argc++] = "--intf=dummy"; + + // loop mode is a configuration option only + if( _b_autoloop ) + ppsz_argv[ppsz_argc++] = "--loop"; + + _p_libvlc = libvlc_new(ppsz_argc, ppsz_argv, NULL); + if( NULL == _p_libvlc ) + { + *pp_libvlc = NULL; + return E_FAIL; + } + + // initial volume setting + libvlc_audio_set_volume(_p_libvlc, _i_volume, NULL); + if( _b_mute ) + { + libvlc_audio_set_mute(_p_libvlc, TRUE, NULL); } - char *psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl); - if( NULL != psz_mrl ) + // initial playlist item + if( SysStringLen(_bstr_mrl) > 0 ) { - // add default target to playlist - char *cOptions[1]; - int cOptionsCount = 0; + char *psz_mrl = NULL; - if( _b_autoloop ) + if( SysStringLen(_bstr_baseurl) > 0 ) { - cOptions[cOptionsCount++] = "loop"; + /* + ** if the MRL a relative URL, we should end up with an absolute URL + */ + LPWSTR abs_url = CombineURL(_bstr_baseurl, _bstr_mrl); + if( NULL != abs_url ) + { + psz_mrl = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url)); + CoTaskMemFree(abs_url); + } + else + { + psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl); + } + } + else + { + /* + ** baseURL is empty, assume MRL is absolute + */ + psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl); + } + if( NULL != psz_mrl ) + { + const char *options[1]; + int i_options = 0; + + char timeBuffer[32]; + if( _i_time ) + { + snprintf(timeBuffer, sizeof(timeBuffer), ":start-time=%d", _i_time); + options[i_options++] = timeBuffer; + } + // add default target to playlist + libvlc_playlist_add_extended(_p_libvlc, psz_mrl, NULL, i_options, options, NULL); + CoTaskMemFree(psz_mrl); } - VLC_AddTarget(_i_vlc, psz_mrl, (const char **)&cOptions, cOptionsCount, PLAYLIST_APPEND, PLAYLIST_END); - CoTaskMemFree(psz_mrl); } } - setDirty(FALSE); + *pp_libvlc = _p_libvlc; return S_OK; }; +void VLCPlugin::setErrorInfo(REFIID riid, const char *description) +{ + vlcSupportErrorInfo->setErrorInfo( getClassID() == CLSID_VLCPlugin2 ? + OLESTR("VideoLAN.VLCPlugin.2") : OLESTR("VideoLAN.VLCPlugin.1"), + riid, description ); +}; + HRESULT VLCPlugin::onAmbientChanged(LPUNKNOWN pContainer, DISPID dispID) { VARIANT v; switch( dispID ) { case DISPID_AMBIENT_BACKCOLOR: + VariantInit(&v); + V_VT(&v) = VT_I4; + if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) ) + { + setBackColor(V_I4(&v)); + } break; case DISPID_AMBIENT_DISPLAYNAME: break; @@ -665,9 +626,9 @@ HRESULT VLCPlugin::onAmbientChanged(LPUNKNOWN pContainer, DISPID dispID) case DISPID_AMBIENT_TOPTOBOTTOM: break; case DISPID_UNKNOWN: - /* - ** multiple property change, look up the ones we are interested in - */ + /* + ** multiple property change, look up the ones we are interested in + */ VariantInit(&v); V_VT(&v) = VT_BOOL; if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_USERMODE, v)) ) @@ -687,19 +648,26 @@ HRESULT VLCPlugin::onAmbientChanged(LPUNKNOWN pContainer, DISPID dispID) HRESULT VLCPlugin::onClose(DWORD dwSaveOption) { - if( _i_vlc ) + if( isInPlaceActive() ) + { + onInPlaceDeactivate(); + } + if( isRunning() ) { - int i_vlc = _i_vlc; + libvlc_instance_t* p_libvlc = _p_libvlc; - _i_vlc = 0; - if( isInPlaceActive() ) + IVLCLog *p_log; + if( SUCCEEDED(vlcControl2->get_log(&p_log)) ) { - onInPlaceDeactivate(); + // make sure the log is disabled + p_log->put_verbosity(-1); + p_log->Release(); } + + _p_libvlc = NULL; vlcDataObject->onClose(); - VLC_CleanUp(i_vlc); - VLC_Destroy(i_vlc); + libvlc_release(p_libvlc, NULL ); } return S_OK; }; @@ -711,32 +679,26 @@ BOOL VLCPlugin::isInPlaceActive(void) HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprcPosRect, LPCRECT lprcClipRect) { - RECT posRect = *lprcPosRect; RECT clipRect = *lprcClipRect; /* ** record keeping of control geometry within container - */ - _posRect = posRect; - - /* - ** convert posRect & clipRect to match control viewport coordinates */ - getViewportCoords(&posRect, &clipRect); + _posRect = *lprcPosRect; /* ** Create a window for in place activated control. ** the window geometry matches the control viewport ** within container so that embedded video is always - ** properly clipped. + ** properly displayed. */ _inplacewnd = CreateWindow(_p_class->getInPlaceWndClassName(), - "VLC Plugin In-Place Window", + TEXT("VLC Plugin In-Place Window"), WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, - clipRect.left, - clipRect.top, - clipRect.right-clipRect.left, - clipRect.bottom-clipRect.top, + lprcPosRect->left, + lprcPosRect->top, + lprcPosRect->right-lprcPosRect->left, + lprcPosRect->bottom-lprcPosRect->top, hwndParent, 0, _p_class->getHInstance(), @@ -748,75 +710,122 @@ HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprc SetWindowLongPtr(_inplacewnd, GWLP_USERDATA, reinterpret_cast(this)); - /* - ** VLC embedded video automatically grows to cover client - ** area of parent window. - ** hence create a such a 'parent' window whose geometry - ** is always correct relative to the viewport bounds - */ - _videownd = CreateWindow(_p_class->getVideoWndClassName(), - "VLC Plugin Video Window", - WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE, - posRect.left, - posRect.top, - posRect.right-posRect.left, - posRect.bottom-posRect.top, - _inplacewnd, - 0, - _p_class->getHInstance(), - NULL - ); + /* change cliprect coordinates system relative to window bounding rect */ + OffsetRect(&clipRect, -lprcPosRect->left, -lprcPosRect->top); - if( NULL == _videownd ) + HRGN clipRgn = CreateRectRgnIndirect(&clipRect); + SetWindowRgn(_inplacewnd, clipRgn, TRUE); + + if( _b_usermode ) { - DestroyWindow(_inplacewnd); - return E_FAIL; + /* will run vlc if not done already */ + libvlc_instance_t* p_libvlc; + HRESULT result = getVLC(&p_libvlc); + if( FAILED(result) ) + return result; + + /* set internal video width and height */ + libvlc_video_set_size(p_libvlc, + lprcPosRect->right-lprcPosRect->left, + lprcPosRect->bottom-lprcPosRect->top, + NULL ); + + /* set internal video parent window */ + libvlc_video_set_parent(p_libvlc, + reinterpret_cast(_inplacewnd), NULL); + + if( _b_autoplay & (libvlc_playlist_items_count(p_libvlc, NULL) > 0) ) + { + libvlc_playlist_play(p_libvlc, 0, 0, NULL, NULL); + fireOnPlayEvent(); + } } - SetWindowLongPtr(_videownd, GWLP_USERDATA, reinterpret_cast(this)); + if( isVisible() ) + ShowWindow(_inplacewnd, SW_SHOW); - if( getVisible() ) - ShowWindow(_inplacewnd, SW_SHOWNORMAL); - - /* set internal video width and height */ - vlc_value_t val; - val.i_int = posRect.right-posRect.left; - VLC_VariableSet(_i_vlc, "conf::width", val); - val.i_int = posRect.bottom-posRect.top; - VLC_VariableSet(_i_vlc, "conf::height", val); - - /* set internal video parent window */ - /* horrible cast there */ - val.i_int = reinterpret_cast(_videownd); - VLC_VariableSet(_i_vlc, "drawable", val); - - if( _b_usermode && _b_autoplay & (VLC_PlaylistNumberOfItems(_i_vlc) > 0) ) - { - VLC_Play(_i_vlc); - fireOnPlayEvent(); - } return S_OK; }; HRESULT VLCPlugin::onInPlaceDeactivate(void) { - VLC_Stop(_i_vlc); - fireOnStopEvent(); + if( isRunning() ) + { + libvlc_playlist_stop(_p_libvlc, NULL); + fireOnStopEvent(); + } - DestroyWindow(_videownd); - _videownd = NULL; DestroyWindow(_inplacewnd); _inplacewnd = NULL; - + return S_OK; }; void VLCPlugin::setVisible(BOOL fVisible) { - _b_visible = fVisible; - if( isInPlaceActive() ) - ShowWindow(_inplacewnd, fVisible ? SW_SHOWNORMAL : SW_HIDE); - firePropChangedEvent(DISPID_Visible); + if( fVisible != _b_visible ) + { + _b_visible = fVisible; + if( isInPlaceActive() ) + { + ShowWindow(_inplacewnd, fVisible ? SW_SHOW : SW_HIDE); + if( fVisible ) + InvalidateRect(_inplacewnd, NULL, TRUE); + } + setDirty(TRUE); + firePropChangedEvent(DISPID_Visible); + } +}; + +void VLCPlugin::setVolume(int volume) +{ + if( volume < 0 ) + volume = 0; + else if( volume > 200 ) + volume = 200; + + if( volume != _i_volume ) + { + _i_volume = volume; + if( isRunning() ) + { + libvlc_audio_set_volume(_p_libvlc, _i_volume, NULL); + } + setDirty(TRUE); + } +}; + +void VLCPlugin::setBackColor(OLE_COLOR backcolor) +{ + if( _i_backcolor != backcolor ) + { + _i_backcolor = backcolor; + if( isInPlaceActive() ) + { + + } + setDirty(TRUE); + } +}; + +void VLCPlugin::setTime(int seconds) +{ + if( seconds < 0 ) + seconds = 0; + + if( seconds != _i_time ) + { + setStartTime(_i_time); + if( isRunning() ) + { + libvlc_media_instance_t *p_md = libvlc_playlist_get_media_instance(_p_libvlc, NULL); + if( NULL != p_md ) + { + libvlc_media_instance_set_time(p_md, _i_time, NULL); + libvlc_media_instance_release(p_md); + } + } + } }; void VLCPlugin::setFocus(BOOL fFocus) @@ -833,72 +842,94 @@ BOOL VLCPlugin::hasFocus(void) void VLCPlugin::onDraw(DVTARGETDEVICE * ptd, HDC hicTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds) { - if( getVisible() ) + if( isVisible() ) { long width = lprcBounds->right-lprcBounds->left; long height = lprcBounds->bottom-lprcBounds->top; RECT bounds = { lprcBounds->left, lprcBounds->top, lprcBounds->right, lprcBounds->bottom }; - FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(WHITE_BRUSH)); - LPPICTURE pict = getPicture(); - if( NULL != pict ) + if( isUserMode() ) { - OLE_XSIZE_HIMETRIC picWidth; - OLE_YSIZE_HIMETRIC picHeight; - - pict->get_Width(&picWidth); - pict->get_Height(&picHeight); - - SIZEL picSize = { picWidth, picHeight }; - - if( NULL != hicTargetDev ) + /* VLC is in user mode, just draw background color */ + COLORREF colorref = RGB(0, 0, 0); + OleTranslateColor(_i_backcolor, (HPALETTE)GetStockObject(DEFAULT_PALETTE), &colorref); + if( colorref != RGB(0, 0, 0) ) { - DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1); + /* custom background */ + HBRUSH colorbrush = CreateSolidBrush(colorref); + FillRect(hdcDraw, &bounds, colorbrush); + DeleteObject((HANDLE)colorbrush); } - else if( NULL != (hicTargetDev = CreateDevDC(ptd)) ) + else { - DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1); - DeleteDC(hicTargetDev); + /* black background */ + FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(BLACK_BRUSH)); } + } + else + { + /* VLC is in design mode, draw the VLC logo */ + FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(WHITE_BRUSH)); - if( picSize.cx > width-4 ) - picSize.cx = width-4; - if( picSize.cy > height-4 ) - picSize.cy = height-4; + LPPICTURE pict = getPicture(); + if( NULL != pict ) + { + OLE_XSIZE_HIMETRIC picWidth; + OLE_YSIZE_HIMETRIC picHeight; - LONG dstX = lprcBounds->left+(width-picSize.cx)/2; - LONG dstY = lprcBounds->top+(height-picSize.cy)/2; + pict->get_Width(&picWidth); + pict->get_Height(&picHeight); - if( NULL != lprcWBounds ) - { - RECT wBounds = { lprcWBounds->left, lprcWBounds->top, lprcWBounds->right, lprcWBounds->bottom }; - pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy, - 0L, picHeight, picWidth, -picHeight, &wBounds); - } - else - pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy, - 0L, picHeight, picWidth, -picHeight, NULL); + SIZEL picSize = { picWidth, picHeight }; - pict->Release(); - } + if( NULL != hicTargetDev ) + { + DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1); + } + else if( NULL != (hicTargetDev = CreateDevDC(ptd)) ) + { + DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1); + DeleteDC(hicTargetDev); + } - SelectObject(hdcDraw, GetStockObject(BLACK_BRUSH)); + if( picSize.cx > width-4 ) + picSize.cx = width-4; + if( picSize.cy > height-4 ) + picSize.cy = height-4; + + LONG dstX = lprcBounds->left+(width-picSize.cx)/2; + LONG dstY = lprcBounds->top+(height-picSize.cy)/2; + + if( NULL != lprcWBounds ) + { + RECT wBounds = { lprcWBounds->left, lprcWBounds->top, lprcWBounds->right, lprcWBounds->bottom }; + pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy, + 0L, picHeight, picWidth, -picHeight, &wBounds); + } + else + pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy, + 0L, picHeight, picWidth, -picHeight, NULL); - MoveToEx(hdcDraw, bounds.left, bounds.top, NULL); - LineTo(hdcDraw, bounds.left+width-1, bounds.top); - LineTo(hdcDraw, bounds.left+width-1, bounds.top+height-1); - LineTo(hdcDraw, bounds.left, bounds.top+height-1); - LineTo(hdcDraw, bounds.left, bounds.top); + pict->Release(); + } + + SelectObject(hdcDraw, GetStockObject(BLACK_BRUSH)); + + MoveToEx(hdcDraw, bounds.left, bounds.top, NULL); + LineTo(hdcDraw, bounds.left+width-1, bounds.top); + LineTo(hdcDraw, bounds.left+width-1, bounds.top+height-1); + LineTo(hdcDraw, bounds.left, bounds.top+height-1); + LineTo(hdcDraw, bounds.left, bounds.top); + } } }; void VLCPlugin::onPaint(HDC hdc, const RECT &bounds, const RECT &clipRect) { - if( getVisible() ) + if( isVisible() ) { - /** if VLC is playing, it may not display any VIDEO content - ** hence, draw control logo*/ + /* if VLC is in design mode, draw control logo */ HDC hdcDraw = CreateCompatibleDC(hdc); if( NULL != hdcDraw ) { @@ -941,52 +972,40 @@ void VLCPlugin::onPaint(HDC hdc, const RECT &bounds, const RECT &clipRect) void VLCPlugin::onPositionChange(LPCRECT lprcPosRect, LPCRECT lprcClipRect) { RECT clipRect = *lprcClipRect; - RECT posRect = *lprcPosRect; //RedrawWindow(GetParent(_inplacewnd), &_posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); /* ** record keeping of control geometry within container */ - _posRect = posRect; - - /* - ** convert posRect & clipRect to match control viewport coordinates - */ - getViewportCoords(&posRect, &clipRect); + _posRect = *lprcPosRect; /* ** change in-place window geometry to match clipping region */ SetWindowPos(_inplacewnd, NULL, - clipRect.left, - clipRect.top, - clipRect.right-clipRect.left, - clipRect.bottom-clipRect.top, + lprcPosRect->left, + lprcPosRect->top, + lprcPosRect->right-lprcPosRect->left, + lprcPosRect->bottom-lprcPosRect->top, SWP_NOACTIVATE| SWP_NOCOPYBITS| SWP_NOZORDER| SWP_NOOWNERZORDER ); - /* - ** change video window geometry to match object bounds within clipping region - */ - SetWindowPos(_videownd, NULL, - posRect.left, - posRect.top, - posRect.right-posRect.left, - posRect.bottom-posRect.top, - SWP_NOACTIVATE| - SWP_NOCOPYBITS| - SWP_NOZORDER| - SWP_NOOWNERZORDER ); + /* change cliprect coordinates system relative to window bounding rect */ + OffsetRect(&clipRect, -lprcPosRect->left, -lprcPosRect->top); + HRGN clipRgn = CreateRectRgnIndirect(&clipRect); + SetWindowRgn(_inplacewnd, clipRgn, FALSE); //RedrawWindow(_videownd, &posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); - vlc_value_t val; - val.i_int = posRect.right-posRect.left; - VLC_VariableSet(_i_vlc, "conf::width", val); - val.i_int = posRect.bottom-posRect.top; - VLC_VariableSet(_i_vlc, "conf::height", val); + if( isRunning() ) + { + libvlc_video_set_size(_p_libvlc, + lprcPosRect->right-lprcPosRect->left, + lprcPosRect->bottom-lprcPosRect->top, + NULL ); + } }; void VLCPlugin::freezeEvents(BOOL freeze) @@ -996,24 +1015,23 @@ void VLCPlugin::freezeEvents(BOOL freeze) void VLCPlugin::firePropChangedEvent(DISPID dispid) { - vlcConnectionPointContainer->firePropChangedEvent(dispid); + vlcConnectionPointContainer->firePropChangedEvent(dispid); }; void VLCPlugin::fireOnPlayEvent(void) { DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; - vlcConnectionPointContainer->fireEvent(DISPID_PlayEvent, &dispparamsNoArgs); + vlcConnectionPointContainer->fireEvent(DISPID_PlayEvent, &dispparamsNoArgs); }; void VLCPlugin::fireOnPauseEvent(void) { DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; - vlcConnectionPointContainer->fireEvent(DISPID_PauseEvent, &dispparamsNoArgs); + vlcConnectionPointContainer->fireEvent(DISPID_PauseEvent, &dispparamsNoArgs); }; void VLCPlugin::fireOnStopEvent(void) { DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; - vlcConnectionPointContainer->fireEvent(DISPID_StopEvent, &dispparamsNoArgs); + vlcConnectionPointContainer->fireEvent(DISPID_StopEvent, &dispparamsNoArgs); }; -