X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=activex%2Fplugin.cpp;h=e2b8a18102d42e0f97809fc1ce6f4025cb3830ec;hb=089c011a6f08dc48ee3a4cd9d8e59e0450fa6454;hp=e6bff8b8bd3a958ccf7f53fda64e00bef94de2c9;hpb=ee6c3bfc7d2f0793e14b50cf312a9b5130a24ea8;p=vlc diff --git a/activex/plugin.cpp b/activex/plugin.cpp index e6bff8b8bd..e2b8a18102 100644 --- a/activex/plugin.cpp +++ b/activex/plugin.cpp @@ -1,7 +1,7 @@ /***************************************************************************** * plugin.cpp: ActiveX control for VLC ***************************************************************************** - * Copyright (C) 2005 VideoLAN + * Copyright (C) 2005 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" @@ -34,11 +34,16 @@ #include "objectsafety.h" #include "vlccontrol.h" #include "viewobject.h" +#include "dataobject.h" #include "utils.h" #include #include +#include +#include +#include +#include using namespace std; @@ -97,13 +102,14 @@ static LRESULT CALLBACK VLCVideoClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance) : _p_class_ref(p_class_ref), - _hinstance(hInstance) + _hinstance(hInstance), + _inplace_picture(NULL) { WNDCLASS wClass; if( ! GetClassInfo(hInstance, getInPlaceWndClassName(), &wClass) ) { - wClass.style = CS_NOCLOSE|CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS; + wClass.style = CS_NOCLOSE|CS_DBLCLKS; wClass.lpfnWndProc = VLCInPlaceClassWndProc; wClass.cbClsExtra = 0; wClass.cbWndExtra = 0; @@ -123,7 +129,7 @@ VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance) : if( ! GetClassInfo(hInstance, getVideoWndClassName(), &wClass) ) { - wClass.style = CS_NOCLOSE|CS_HREDRAW|CS_VREDRAW; + wClass.style = CS_NOCLOSE; wClass.lpfnWndProc = VLCVideoClassWndProc; wClass.cbClsExtra = 0; wClass.cbWndExtra = 0; @@ -141,8 +147,19 @@ VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance) : _video_wndclass_atom = 0; } - _inplace_hbitmap = (HBITMAP)LoadImage(getHInstance(), TEXT("INPLACE-PICT"), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); + HBITMAP hbitmap = (HBITMAP)LoadImage(getHInstance(), TEXT("INPLACE-PICT"), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); + if( NULL != hbitmap ) + { + PICTDESC pictDesc; + + pictDesc.cbSizeofstruct = sizeof(PICTDESC); + pictDesc.picType = PICTYPE_BITMAP; + pictDesc.bmp.hbitmap = hbitmap; + pictDesc.bmp.hpal = NULL; + if( FAILED(OleCreatePictureIndirect(&pictDesc, IID_IPicture, TRUE, reinterpret_cast(&_inplace_picture))) ) + _inplace_picture = NULL; + } AddRef(); }; @@ -154,8 +171,8 @@ VLCPluginClass::~VLCPluginClass() if( 0 != _video_wndclass_atom ) UnregisterClass(MAKEINTATOM(_video_wndclass_atom), _hinstance); - if( NULL != _inplace_hbitmap ) - DeleteObject(_inplace_hbitmap); + if( NULL != _inplace_picture ) + _inplace_picture->Release(); }; STDMETHODIMP VLCPluginClass::QueryInterface(REFIID riid, void **ppv) @@ -192,17 +209,18 @@ STDMETHODIMP_(ULONG) VLCPluginClass::Release(void) return refcount; }; -STDMETHODIMP VLCPluginClass::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv) +STDMETHODIMP VLCPluginClass::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppv) { if( NULL == ppv ) return E_POINTER; *ppv = NULL; - if( NULL != pUnkOuter ) + if( (NULL != pUnkOuter) && (IID_IUnknown != riid) ) { return CLASS_E_NOAGGREGATION; + } - VLCPlugin *plugin = new VLCPlugin(this); + VLCPlugin *plugin = new VLCPlugin(this, pUnkOuter); if( NULL != plugin ) { HRESULT hr = plugin->QueryInterface(riid, ppv); @@ -224,22 +242,17 @@ STDMETHODIMP VLCPluginClass::LockServer(BOOL fLock) //////////////////////////////////////////////////////////////////////// -VLCPlugin::VLCPlugin(VLCPluginClass *p_class) : +VLCPlugin::VLCPlugin(VLCPluginClass *p_class, LPUNKNOWN pUnkOuter) : _inplacewnd(NULL), + _videownd(NULL), _p_class(p_class), _i_ref(1UL), - _codepage(CP_ACP), - _psz_src(NULL), - _b_autostart(TRUE), - _b_loopmode(FALSE), - _b_visible(TRUE), - _b_mute(FALSE), - _b_sendevents(TRUE), + _i_codepage(CP_ACP), + _b_usermode(TRUE), _i_vlc(0) { p_class->AddRef(); - vlcOleObject = new VLCOleObject(this); vlcOleControl = new VLCOleControl(this); vlcOleInPlaceObject = new VLCOleInPlaceObject(this); vlcOleInPlaceActiveObject = new VLCOleInPlaceActiveObject(this); @@ -251,22 +264,25 @@ VLCPlugin::VLCPlugin(VLCPluginClass *p_class) : vlcObjectSafety = new VLCObjectSafety(this); vlcControl = new VLCControl(this); vlcViewObject = new VLCViewObject(this); + vlcDataObject = new VLCDataObject(this); + vlcOleObject = new VLCOleObject(this); + + // configure controlling IUnknown interface for implemented interfaces + this->pUnkOuter = (NULL != pUnkOuter) ? pUnkOuter : dynamic_cast(this); + + // default picure + _p_pict = p_class->getInPlacePict(); - // set default/preferred size (320x240) pixels in HIMETRIC - HDC hDC = CreateDevDC(NULL); - _extent.cx = (320*2540L)/GetDeviceCaps(hDC, LOGPIXELSX); - _extent.cy = (240*2540L)/GetDeviceCaps(hDC, LOGPIXELSY); - DeleteDC(hDC); + // make sure that persistable properties are initialized + onInit(); }; VLCPlugin::~VLCPlugin() { - vlcOleInPlaceObject->UIDeactivate(); - vlcOleInPlaceObject->InPlaceDeactivate(); - + delete vlcOleObject; + delete vlcDataObject; delete vlcViewObject; delete vlcControl; - delete vlcObjectSafety; delete vlcConnectionPointContainer; delete vlcProvideClassInfo; delete vlcPersistPropertyBag; @@ -274,11 +290,13 @@ VLCPlugin::~VLCPlugin() delete vlcPersistStorage; delete vlcOleInPlaceActiveObject; delete vlcOleInPlaceObject; + delete vlcObjectSafety; + delete vlcOleControl; - delete vlcOleObject; + if( _p_pict ) + _p_pict->Release(); - if( _psz_src ) - free(_psz_src); + SysFreeString(_bstr_mrl); _p_class->Release(); }; @@ -289,117 +307,50 @@ STDMETHODIMP VLCPlugin::QueryInterface(REFIID riid, void **ppv) return E_INVALIDARG; if( IID_IUnknown == riid ) - { - AddRef(); *ppv = reinterpret_cast(this); - return NOERROR; - } else if( IID_IOleObject == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcOleObject); - return NOERROR; - } else if( IID_IOleControl == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcOleControl); - return NOERROR; - } else if( IID_IOleWindow == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcOleInPlaceObject); - return NOERROR; - } else if( IID_IOleInPlaceObject == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcOleInPlaceObject); - return NOERROR; - } else if( IID_IOleInPlaceActiveObject == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcOleInPlaceActiveObject); - return NOERROR; - } else if( IID_IPersist == riid ) - { - AddRef(); - *ppv = reinterpret_cast(vlcPersistPropertyBag); - return NOERROR; - } + *ppv = reinterpret_cast(vlcPersistStreamInit); else if( IID_IPersistStreamInit == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcPersistStreamInit); - return NOERROR; - } else if( IID_IPersistStorage == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcPersistStorage); - return NOERROR; - } else if( IID_IPersistPropertyBag == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcPersistPropertyBag); - return NOERROR; - } else if( IID_IProvideClassInfo == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcProvideClassInfo); - return NOERROR; - } else if( IID_IProvideClassInfo2 == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcProvideClassInfo); - return NOERROR; - } else if( IID_IConnectionPointContainer == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcConnectionPointContainer); - return NOERROR; - } else if( IID_IObjectSafety == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcObjectSafety); - return NOERROR; - } else if( IID_IDispatch == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcControl); - return NOERROR; - } else if( IID_IVLCControl == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcControl); - return NOERROR; - } else if( IID_IViewObject == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcViewObject); - return NOERROR; - } else if( IID_IViewObject2 == riid ) - { - AddRef(); *ppv = reinterpret_cast(vlcViewObject); - return NOERROR; + else if( IID_IDataObject == riid ) + *ppv = reinterpret_cast(vlcDataObject); + else + { + *ppv = NULL; + return E_NOINTERFACE; } - - *ppv = NULL; - - return E_NOINTERFACE; + ((LPUNKNOWN)*ppv)->AddRef(); + return NOERROR; }; STDMETHODIMP_(ULONG) VLCPlugin::AddRef(void) @@ -515,11 +466,96 @@ HRESULT VLCPlugin::onInit(void) { if( 0 == _i_vlc ) { -#ifdef ACTIVEX_DEBUG - char *ppsz_argv[] = { "vlc", "-vvv", "--fast-mutex", "--win9x-cv-method=1" }; -#else - char *ppsz_argv[] = { "vlc", "-vv" }; -#endif + // initialize persistable properties + _bstr_mrl = NULL; + _b_autoplay = TRUE; + _b_autoloop = FALSE; + _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); + + return S_OK; + } + return CO_E_ALREADYINITIALIZED; +}; + +HRESULT VLCPlugin::onLoad(void) +{ + if( SysStringLen(_bstr_mrl) > 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 + */ + LPOLECLIENTSITE pClientSite; + if( SUCCEEDED(vlcOleObject->GetClientSite(&pClientSite)) && (NULL != pClientSite) ) + { + 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) ) + { + 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); + } + } + CoTaskMemFree(base_url); + } + pContMoniker->Release(); + } + pBC->Release(); + } + pClientSite->Release(); + } + } + setDirty(FALSE); + return S_OK; +}; + +HRESULT VLCPlugin::getVLCObject(int *i_vlc) +{ + if( ! isRunning() ) + { + _i_vlc = VLC_Create(); + if( _i_vlc < 0 ) + { + _i_vlc = 0; + return E_FAIL; + } + + /* + ** default initialization options + */ + char *ppsz_argv[10] = { "vlc", }; + int ppsz_argc = 1; + HKEY h_key; DWORD i_type, i_data = MAX_PATH + 1; char p_data[MAX_PATH + 1]; @@ -542,67 +578,155 @@ HRESULT VLCPlugin::onInit(void) ppsz_argv[0] = "C:\\cygwin\\home\\Damien_Fouilleul\\dev\\videolan\\vlc-trunk\\vlc"; #endif - _i_vlc = VLC_Create(); + // make sure plugin isn't affected with VLC single instance mode + ppsz_argv[ppsz_argc++] = "--no-one-instance"; + + // 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 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 E_UNEXPECTED; -}; -HRESULT VLCPlugin::onLoad(void) -{ - if( _b_mute ) - VLC_VolumeMute(_i_vlc); + VLC_VolumeSet(_i_vlc, _i_volume); - if( NULL != _psz_src ) - { - // add default target to playlist - char *cOptions[1]; - int cOptionsCount = 0; + if( _b_mute ) + VLC_VolumeMute(_i_vlc); - if( _b_loopmode ) + char *psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl); + if( NULL != psz_mrl ) { - cOptions[cOptionsCount++] = "loop"; + char timeBuffer[32]; + const char *options[1]; + int cOptions = 0; + + if( _i_time ) + { + snprintf(timeBuffer, sizeof(timeBuffer), ":start-time=%d", _i_time); + options[cOptions++] = timeBuffer; + } + // add default target to playlist + VLC_AddTarget(_i_vlc, psz_mrl, options, cOptions, PLAYLIST_APPEND, PLAYLIST_END); + CoTaskMemFree(psz_mrl); } - VLC_AddTarget(_i_vlc, _psz_src, (const char **)&cOptions, cOptionsCount, PLAYLIST_APPEND, PLAYLIST_END); } + *i_vlc = _i_vlc; return S_OK; }; -HRESULT VLCPlugin::onClientSiteChanged(LPOLECLIENTSITE pActiveSite) +HRESULT VLCPlugin::onAmbientChanged(LPUNKNOWN pContainer, DISPID dispID) { - if( NULL != pActiveSite ) + VARIANT v; + switch( dispID ) { - /* - ** object is embedded in container - ** try to activate in place if it has initialized - */ - if( _i_vlc ) - { - vlcOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, pActiveSite, 0, NULL, NULL); - } + case DISPID_AMBIENT_BACKCOLOR: + break; + case DISPID_AMBIENT_DISPLAYNAME: + break; + case DISPID_AMBIENT_FONT: + break; + case DISPID_AMBIENT_FORECOLOR: + break; + case DISPID_AMBIENT_LOCALEID: + break; + case DISPID_AMBIENT_MESSAGEREFLECT: + break; + case DISPID_AMBIENT_SCALEUNITS: + break; + case DISPID_AMBIENT_TEXTALIGN: + break; + case DISPID_AMBIENT_USERMODE: + VariantInit(&v); + V_VT(&v) = VT_BOOL; + if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) ) + { + setUserMode(V_BOOL(&v) != VARIANT_FALSE); + } + break; + case DISPID_AMBIENT_UIDEAD: + break; + case DISPID_AMBIENT_SHOWGRABHANDLES: + break; + case DISPID_AMBIENT_SHOWHATCHING: + break; + case DISPID_AMBIENT_DISPLAYASDEFAULT: + break; + case DISPID_AMBIENT_SUPPORTSMNEMONICS: + break; + case DISPID_AMBIENT_AUTOCLIP: + break; + case DISPID_AMBIENT_APPEARANCE: + break; + case DISPID_AMBIENT_CODEPAGE: + VariantInit(&v); + V_VT(&v) = VT_I4; + if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) ) + { + setCodePage(V_I4(&v)); + } + break; + case DISPID_AMBIENT_PALETTE: + break; + case DISPID_AMBIENT_CHARSET: + break; + case DISPID_AMBIENT_RIGHTTOLEFT: + break; + 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); + } + VariantInit(&v); + V_VT(&v) = VT_I4; + if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_CODEPAGE, v)) ) + { + setCodePage(V_I4(&v)); + } + break; } return S_OK; }; HRESULT VLCPlugin::onClose(DWORD dwSaveOption) { - if( _i_vlc ) + if( isInPlaceActive() ) { - if( isInPlaceActive() ) - { - onInPlaceDeactivate(); - } + onInPlaceDeactivate(); + } + if( isRunning() ) + { + int i_vlc = _i_vlc; - VLC_CleanUp(_i_vlc); - VLC_Destroy(_i_vlc); _i_vlc = 0; + vlcDataObject->onClose(); + + VLC_CleanUp(i_vlc); + VLC_Destroy(i_vlc); } return S_OK; }; @@ -629,12 +753,13 @@ HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprc /* ** 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 clipped. */ _inplacewnd = CreateWindow(_p_class->getInPlaceWndClassName(), "VLC Plugin In-Place Window", - WS_CHILD|WS_CLIPCHILDREN|WS_TABSTOP, + WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, clipRect.left, clipRect.top, clipRect.right-clipRect.left, @@ -651,8 +776,9 @@ 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 + ** 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(), @@ -676,26 +802,46 @@ HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprc SetWindowLongPtr(_videownd, GWLP_USERDATA, reinterpret_cast(this)); - if( getVisible() ) - ShowWindow(_inplacewnd, SW_SHOWNORMAL); - - /* horrible cast there */ - vlc_value_t val; - val.i_int = reinterpret_cast(_videownd); - VLC_VariableSet(_i_vlc, "drawable", val); - - if( _b_autostart & (VLC_PlaylistNumberOfItems(_i_vlc) > 0) ) + if( _b_usermode ) { - VLC_Play(_i_vlc); - fireOnPlayEvent(); + /* will run vlc if not done already */ + int i_vlc; + HRESULT result = getVLCObject(&i_vlc); + if( FAILED(result) ) + return result; + + /* 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_autoplay & (VLC_PlaylistNumberOfItems(i_vlc) > 0) ) + { + VLC_Play(i_vlc); + fireOnPlayEvent(); + } } + + if( isVisible() ) + ShowWindow(_inplacewnd, SW_SHOW); + return S_OK; }; HRESULT VLCPlugin::onInPlaceDeactivate(void) { - VLC_Stop(_i_vlc); - fireOnStopEvent(); + if( isRunning() ) + { + VLC_Stop(_i_vlc); + fireOnStopEvent(); + } DestroyWindow(_videownd); _videownd = NULL; @@ -707,10 +853,52 @@ HRESULT VLCPlugin::onInPlaceDeactivate(void) 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(_videownd, 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() ) + { + VLC_VolumeSet(_i_vlc, _i_volume); + } + setDirty(TRUE); + } +}; + +void VLCPlugin::setTime(int seconds) +{ + if( seconds < 0 ) + seconds = 0; + + if( seconds != _i_time ) + { + _i_time = seconds; + if( isRunning() ) + { + VLC_TimeSet(_i_vlc, seconds, VLC_FALSE); + } + setDirty(TRUE); + } }; void VLCPlugin::setFocus(BOOL fFocus) @@ -724,54 +912,111 @@ BOOL VLCPlugin::hasFocus(void) return GetActiveWindow() == _inplacewnd; }; -void VLCPlugin::onPaint(HDC hdc, const RECT &bounds, const RECT &pr) +void VLCPlugin::onDraw(DVTARGETDEVICE * ptd, HDC hicTargetDev, + HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds) { - if( getVisible() ) + if( isVisible() ) { - /* - ** if VLC is playing, it may not display any VIDEO content - ** hence, draw control logo - */ - int width = bounds.right-bounds.left; - int height = bounds.bottom-bounds.top; + 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)); - HBITMAP pict = _p_class->getInPlacePict(); + LPPICTURE pict = getPicture(); if( NULL != pict ) { - HDC hdcPict = CreateCompatibleDC(hdc); - if( NULL != hdcPict ) + OLE_XSIZE_HIMETRIC picWidth; + OLE_YSIZE_HIMETRIC picHeight; + + pict->get_Width(&picWidth); + pict->get_Height(&picHeight); + + SIZEL picSize = { picWidth, picHeight }; + + if( NULL != hicTargetDev ) { - BITMAP bm; - if( GetObject(pict, sizeof(BITMAPINFO), &bm) ) - { - int dstWidth = bm.bmWidth; - if( dstWidth > width-4 ) - dstWidth = width-4; - - int dstHeight = bm.bmHeight; - if( dstHeight > height-4 ) - dstHeight = height-4; - - int dstX = bounds.left+(width-dstWidth)/2; - int dstY = bounds.top+(height-dstHeight)/2; - - SelectObject(hdcPict, pict); - StretchBlt(hdc, dstX, dstY, dstWidth, dstHeight, - hdcPict, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); - DeleteDC(hdcPict); - ExcludeClipRect(hdc, dstX, dstY, dstWidth+dstX, dstHeight+dstY); - } + DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1); + } + else if( NULL != (hicTargetDev = CreateDevDC(ptd)) ) + { + DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1); + DeleteDC(hicTargetDev); } + + 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); + + pict->Release(); } - FillRect(hdc, &pr, (HBRUSH)GetStockObject(WHITE_BRUSH)); - SelectObject(hdc, GetStockObject(BLACK_BRUSH)); + SelectObject(hdcDraw, GetStockObject(BLACK_BRUSH)); - MoveToEx(hdc, bounds.left, bounds.top, NULL); - LineTo(hdc, bounds.left+width-1, bounds.top); - LineTo(hdc, bounds.left+width-1, bounds.top+height-1); - LineTo(hdc, bounds.left, bounds.top+height-1); - LineTo(hdc, bounds.left, bounds.top); + 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( isVisible() ) + { + /** if VLC is playing, it may not display any VIDEO content + ** hence, draw control logo*/ + HDC hdcDraw = CreateCompatibleDC(hdc); + if( NULL != hdcDraw ) + { + SIZEL size = getExtent(); + DPFromHimetric(hdc, (LPPOINT)&size, 1); + RECTL posRect = { 0, 0, size.cx, size.cy }; + + int width = bounds.right-bounds.left; + int height = bounds.bottom-bounds.top; + + HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height); + if( NULL != hBitmap ) + { + HBITMAP oldBmp = (HBITMAP)SelectObject(hdcDraw, hBitmap); + + if( (size.cx != width) || (size.cy != height) ) + { + // needs to scale canvas + SetMapMode(hdcDraw, MM_ANISOTROPIC); + SetWindowExtEx(hdcDraw, size.cx, size.cy, NULL); + SetViewportExtEx(hdcDraw, width, height, NULL); + } + + onDraw(NULL, hdc, hdcDraw, &posRect, NULL); + + SetMapMode(hdcDraw, MM_TEXT); + BitBlt(hdc, bounds.left, bounds.top, + width, height, + hdcDraw, 0, 0, + SRCCOPY); + + SelectObject(hdcDraw, oldBmp); + DeleteObject(hBitmap); + } + DeleteDC(hdcDraw); + } } }; @@ -780,16 +1025,11 @@ void VLCPlugin::onPositionChange(LPCRECT lprcPosRect, LPCRECT lprcClipRect) RECT clipRect = *lprcClipRect; RECT posRect = *lprcPosRect; - /* - ** tell container that previous area needs redrawing - */ - - InvalidateRect(GetParent(_inplacewnd), &_posRect, TRUE); + //RedrawWindow(GetParent(_inplacewnd), &_posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); /* ** record keeping of control geometry within container */ - _posRect = posRect; /* @@ -800,69 +1040,62 @@ void VLCPlugin::onPositionChange(LPCRECT lprcPosRect, LPCRECT lprcClipRect) /* ** change in-place window geometry to match clipping region */ - MoveWindow(_inplacewnd, + SetWindowPos(_inplacewnd, NULL, clipRect.left, clipRect.top, clipRect.right-clipRect.left, clipRect.bottom-clipRect.top, - FALSE); + SWP_NOACTIVATE| + SWP_NOCOPYBITS| + SWP_NOZORDER| + SWP_NOOWNERZORDER ); /* ** change video window geometry to match object bounds within clipping region */ - MoveWindow(_videownd, + SetWindowPos(_videownd, NULL, posRect.left, posRect.top, posRect.right-posRect.left, posRect.bottom-posRect.top, - FALSE); + SWP_NOACTIVATE| + SWP_NOCOPYBITS| + SWP_NOZORDER| + SWP_NOOWNERZORDER ); - /* - ** force a full refresh of control content - */ - RECT updateRect; - updateRect.left = -posRect.left; - updateRect.top = -posRect.top; - updateRect.right = posRect.right-posRect.left; - updateRect.bottom = posRect.bottom-posRect.top; + //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); +}; - ValidateRect(_videownd, NULL); - InvalidateRect(_videownd, &updateRect, FALSE); - UpdateWindow(_videownd); +void VLCPlugin::freezeEvents(BOOL freeze) +{ + vlcConnectionPointContainer->freezeEvents(freeze); }; void VLCPlugin::firePropChangedEvent(DISPID dispid) { - if( _b_sendevents ) - { - vlcConnectionPointContainer->firePropChangedEvent(dispid); - } + vlcConnectionPointContainer->firePropChangedEvent(dispid); }; void VLCPlugin::fireOnPlayEvent(void) { - if( _b_sendevents ) - { - DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; - vlcConnectionPointContainer->fireEvent(DISPID_PlayEvent, &dispparamsNoArgs); - } + DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; + vlcConnectionPointContainer->fireEvent(DISPID_PlayEvent, &dispparamsNoArgs); }; void VLCPlugin::fireOnPauseEvent(void) { - if( _b_sendevents ) - { - DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; - vlcConnectionPointContainer->fireEvent(DISPID_PauseEvent, &dispparamsNoArgs); - } + DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; + vlcConnectionPointContainer->fireEvent(DISPID_PauseEvent, &dispparamsNoArgs); }; void VLCPlugin::fireOnStopEvent(void) { - if( _b_sendevents ) - { - DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; - vlcConnectionPointContainer->fireEvent(DISPID_StopEvent, &dispparamsNoArgs); - } + DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; + vlcConnectionPointContainer->fireEvent(DISPID_StopEvent, &dispparamsNoArgs); };