X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=activex%2Fplugin.cpp;h=348d1419b57f23e5055bf0f373e806258285a32d;hb=1148a9e41bf38bde489c5fea014aad10a3d5cfd8;hp=67a8965bc53d2c3fc14c0da6187ad9b801c273bf;hpb=e373df9de49e94237944cb31f917b4ee5815506e;p=vlc diff --git a/activex/plugin.cpp b/activex/plugin.cpp index 67a8965bc5..348d1419b5 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 * @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #include "plugin.h" @@ -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,11 @@ 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) + _hinstance(hInstance), + _classid(rclsid), + _inplace_picture(NULL) { WNDCLASS wClass; @@ -118,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 @@ -126,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 ) { @@ -167,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(); }; @@ -179,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); @@ -223,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; } @@ -245,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(); @@ -266,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); @@ -276,19 +232,17 @@ 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() { + delete vlcSupportErrorInfo; delete vlcOleObject; delete vlcDataObject; delete vlcViewObject; + delete vlcControl2; delete vlcControl; delete vlcConnectionPointContainer; delete vlcProvideClassInfo; @@ -303,7 +257,8 @@ VLCPlugin::~VLCPlugin() if( _p_pict ) _p_pict->Release(); - SysFreeString(_bstr_mrl), + SysFreeString(_bstr_mrl); + SysFreeString(_bstr_baseurl); _p_class->Release(); }; @@ -342,15 +297,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; @@ -377,211 +338,237 @@ 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) +HRESULT VLCPlugin::onInit(void) { - RECT bounds; - bounds.right = lprPosRect->right-lprPosRect->left; - - if( lprClipRect->left <= lprPosRect->left ) + if( NULL == _p_libvlc ) { - // left side is not clipped out - bounds.left = 0; + // 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; + // 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); - 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; - } + return S_OK; } - else - { - // left side is clipped out - bounds.left = lprPosRect->left-lprClipRect->left; - bounds.right += bounds.left; + return CO_E_ALREADYINITIALIZED; +}; - lprPosRect->left = lprClipRect->left; - if( lprClipRect->right >= lprPosRect->right ) - { - // right side is not clipped out - } - else +HRESULT VLCPlugin::onLoad(void) +{ + if( SysStringLen(_bstr_baseurl) == 0 ) + { + /* + ** 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. + */ + LPOLECLIENTSITE pClientSite; + if( SUCCEEDED(vlcOleObject->GetClientSite(&pClientSite)) && (NULL != pClientSite) ) { - // right side is clipped out - lprPosRect->right = lprClipRect->right; + IBindCtx *pBC = 0; + if( SUCCEEDED(CreateBindCtx(0, &pBC)) ) + { + LPMONIKER pContMoniker = NULL; + if( SUCCEEDED(pClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE, + OLEWHICHMK_CONTAINER, &pContMoniker)) ) + { + LPOLESTR base_url; + if( SUCCEEDED(pContMoniker->GetDisplayName(pBC, NULL, &base_url)) ) + { + /* + ** check that the moniker name is a URL + */ + if( UrlIsW(base_url, URLIS_URL) ) + { + /* copy base URL */ + _bstr_baseurl = SysAllocString(base_url); + } + CoTaskMemFree(base_url); + } + } + } } } + setDirty(FALSE); + return S_OK; +}; - bounds.bottom = lprPosRect->bottom-lprPosRect->top; - - if( lprClipRect->top <= lprPosRect->top ) +HRESULT VLCPlugin::getVLCObject(int* i_vlc) +{ + libvlc_instance_t *p_libvlc; + HRESULT result = getVLC(&p_libvlc); + if( SUCCEEDED(result) ) { - // 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; - } + *i_vlc = libvlc_get_vlc_id(p_libvlc); } 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; - } + *i_vlc = 0; } - *lprClipRect = *lprPosRect; - *lprPosRect = bounds; -}; + return result; +} -HRESULT VLCPlugin::onInit(void) +HRESULT VLCPlugin::getVLC(libvlc_instance_t** pp_libvlc) { - if( 0 == _i_vlc ) + extern HMODULE DllGetModule(); + + if( ! isRunning() ) { -//#ifdef ACTIVEX_DEBUG -#if 1 - char *ppsz_argv[] = { "vlc", "-vv", "--fast-mutex", "--win9x-cv-method=1" }; -#else - char *ppsz_argv[] = { "vlc", "-vv" }; -#endif + /* + ** 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; - DWORD i_type, i_data = MAX_PATH + 1; - char p_data[MAX_PATH + 1]; - if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\VideoLAN\\VLC", + char p_pluginpath[MAX_PATH]; + if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("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 ); + 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 ); } -#if 0 - ppsz_argv[0] = "C:\\cygwin\\home\\Damien_Fouilleul\\dev\\videolan\\vlc-trunk\\vlc"; -#endif + // 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"; - _i_vlc = VLC_Create(); + // loop mode is a configuration option only + if( _b_autoloop ) + ppsz_argv[ppsz_argc++] = "--loop"; - if( VLC_Init(_i_vlc, sizeof(ppsz_argv)/sizeof(char*), ppsz_argv) ) + if( IsDebuggerPresent() ) { - VLC_Destroy(_i_vlc); - _i_vlc = 0; + /* + ** 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"; + } + +DebugBreak(); + + _p_libvlc = libvlc_new(ppsz_argc, ppsz_argv, NULL); + if( NULL == _p_libvlc ) + { + *pp_libvlc = NULL; return E_FAIL; } - return S_OK; - } - return CO_E_ALREADYINITIALIZED; -}; -HRESULT VLCPlugin::onLoad(void) -{ - if( _b_mute ) - VLC_VolumeMute(_i_vlc); + // initial volume setting + libvlc_audio_set_volume(_p_libvlc, _i_volume, NULL); + if( _b_mute ) + { + libvlc_audio_set_mute(_p_libvlc, TRUE, NULL); + } - if( NULL != _bstr_mrl ) - { - /* - ** 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 - */ - IOleClientSite *pClientSite; - if( SUCCEEDED(vlcOleObject->GetClientSite(&pClientSite)) ) + // initial playlist item + if( SysStringLen(_bstr_mrl) > 0 ) { - IBindCtx *pBC = 0; - if( SUCCEEDED(CreateBindCtx(0, &pBC)) ) + char *psz_mrl = NULL; + + if( SysStringLen(_bstr_baseurl) > 0 ) { - LPMONIKER pContMoniker = NULL; - if( SUCCEEDED(pClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE, - OLEWHICHMK_CONTAINER, &pContMoniker)) ) + /* + ** 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 ) { - LPOLESTR name; - if( SUCCEEDED(pContMoniker->GetDisplayName(pBC, NULL, &name)) ) - { - if( UrlIsW(name, URLIS_URL) ) - { - LPOLESTR url = (LPOLESTR)CoTaskMemAlloc(sizeof(OLECHAR)*INTERNET_MAX_URL_LENGTH); - if( NULL != url ) - { - DWORD len = INTERNET_MAX_URL_LENGTH; - if( SUCCEEDED(UrlCombineW(name, _bstr_mrl, url, &len, - URL_ESCAPE_UNSAFE)) ) - { - SysFreeString(_bstr_mrl); - _bstr_mrl = SysAllocString(url); - } - CoTaskMemFree(url); - } - } - CoTaskMemFree(name); - } - pContMoniker->Release(); + psz_mrl = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url)); + CoTaskMemFree(abs_url); + } + else + { + psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl); } - pBC->Release(); } - pClientSite->Release(); - } - - char *psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl); - if( NULL != psz_mrl ) - { - // add default target to playlist - char *cOptions[1]; - int cOptionsCount = 0; - - if( _b_autoloop ) + else { - cOptions[cOptionsCount++] = "loop"; + /* + ** 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; @@ -609,7 +596,6 @@ HRESULT VLCPlugin::onAmbientChanged(LPUNKNOWN pContainer, DISPID dispID) if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) ) { setUserMode(V_BOOL(&v) != VARIANT_FALSE); - VariantClear(&v); } break; case DISPID_AMBIENT_UIDEAD: @@ -643,16 +629,18 @@ 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 + */ VariantInit(&v); V_VT(&v) = VT_BOOL; if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_USERMODE, v)) ) { setUserMode(V_BOOL(&v) != VARIANT_FALSE); - VariantClear(&v); } VariantInit(&v); V_VT(&v) = VT_I4; - if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) ) + if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_CODEPAGE, v)) ) { setCodePage(V_I4(&v)); } @@ -663,19 +651,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_destroy(p_libvlc, NULL ); } return S_OK; }; @@ -687,31 +682,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 represents the control viewport - ** so that embedded video is always properly clipped. + ** the window geometry matches the control viewport + ** within container so that embedded video is always + ** 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(), @@ -723,71 +713,109 @@ HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprc SetWindowLongPtr(_inplacewnd, GWLP_USERDATA, reinterpret_cast(this)); - /* - ** VLC embedded video geometry automatically matches parent window. - ** hence create a child window so that video position and size - ** 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); + + HRGN clipRgn = CreateRectRgnIndirect(&clipRect); + SetWindowRgn(_inplacewnd, clipRgn, TRUE); - if( NULL == _videownd ) + 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( getVisible() ) - ShowWindow(_inplacewnd, SW_SHOWNORMAL); + if( isVisible() ) + ShowWindow(_inplacewnd, SW_SHOW); - /* horrible cast there */ - vlc_value_t val; - val.i_int = reinterpret_cast(_videownd); - VLC_VariableSet(_i_vlc, "drawable", val); - val.i_int = posRect.right-posRect.left; - VLC_VariableSet(_i_vlc, "width", val); - val.i_int = posRect.bottom-posRect.top; - VLC_VariableSet(_i_vlc, "height", 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::setTime(int seconds) +{ + if( seconds < 0 ) + seconds = 0; + + if( seconds != _i_time ) + { + setStartTime(_i_time); + if( isRunning() ) + { + libvlc_input_t *p_input = libvlc_playlist_get_input(_p_libvlc, NULL); + if( NULL != p_input ) + { + libvlc_input_set_time(p_input, _i_time, NULL); + libvlc_input_free(p_input); + } + } + } }; void VLCPlugin::setFocus(BOOL fFocus) @@ -804,7 +832,7 @@ 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; @@ -866,7 +894,7 @@ void VLCPlugin::onDraw(DVTARGETDEVICE * ptd, HDC hicTargetDev, 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*/ @@ -885,7 +913,7 @@ void VLCPlugin::onPaint(HDC hdc, const RECT &bounds, const RECT &clipRect) { HBITMAP oldBmp = (HBITMAP)SelectObject(hdcDraw, hBitmap); - if( (size.cx != width) || (size.cx != height) ) + if( (size.cx != width) || (size.cy != height) ) { // needs to scale canvas SetMapMode(hdcDraw, MM_ANISOTROPIC); @@ -912,52 +940,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, "width", val); - val.i_int = posRect.bottom-posRect.top; - VLC_VariableSet(_i_vlc, "height", val); + if( isRunning() ) + { + libvlc_video_set_size(_p_libvlc, + lprcPosRect->right-lprcPosRect->left, + lprcPosRect->bottom-lprcPosRect->top, + NULL ); + } }; void VLCPlugin::freezeEvents(BOOL freeze) @@ -987,4 +1003,3 @@ void VLCPlugin::fireOnStopEvent(void) DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; vlcConnectionPointContainer->fireEvent(DISPID_StopEvent, &dispparamsNoArgs); }; -