Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

plugin.cpp

00001 /*****************************************************************************
00002  * plugin.cpp: ActiveX control for VLC
00003  *****************************************************************************
00004  * Copyright (C) 2005 the VideoLAN team
00005  *
00006  * Authors: Damien Fouilleul <[email protected]>
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00021  *****************************************************************************/
00022 
00023 #include "plugin.h"
00024 
00025 #include "oleobject.h"
00026 #include "olecontrol.h"
00027 #include "oleinplaceobject.h"
00028 #include "oleinplaceactiveobject.h"
00029 #include "persistpropbag.h"
00030 #include "persiststreaminit.h"
00031 #include "persiststorage.h"
00032 #include "provideclassinfo.h"
00033 #include "connectioncontainer.h"
00034 #include "objectsafety.h"
00035 #include "vlccontrol.h"
00036 #include "viewobject.h"
00037 #include "dataobject.h"
00038 
00039 #include "utils.h"
00040 
00041 #include <string.h>
00042 #include <winreg.h>
00043 #include <winuser.h>
00044 #include <servprov.h>
00045 #include <shlwapi.h>
00046 #include <wininet.h>
00047 
00048 using namespace std;
00049 
00051 //class factory
00052 
00053 // {E23FE9C6-778E-49d4-B537-38FCDE4887D8}
00054 //const GUID CLSID_VLCPlugin = 
00055 //    { 0xe23fe9c6, 0x778e, 0x49d4, { 0xb5, 0x37, 0x38, 0xfc, 0xde, 0x48, 0x87, 0xd8 } };
00056 
00057 static LRESULT CALLBACK VLCInPlaceClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
00058     switch( uMsg )
00059     {
00060         case WM_ERASEBKGND:
00061             return 1L;
00062 
00063         case WM_PAINT:
00064             PAINTSTRUCT ps;
00065             if( GetUpdateRect(hWnd, NULL, FALSE) )
00066             {
00067                 BeginPaint(hWnd, &ps);
00068                 EndPaint(hWnd, &ps);
00069             }
00070             return 0L;
00071 
00072         default:
00073             return DefWindowProc(hWnd, uMsg, wParam, lParam);
00074     }
00075 };
00076 
00077 static LRESULT CALLBACK VLCVideoClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
00078     VLCPlugin *p_instance = reinterpret_cast<VLCPlugin *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
00079 
00080     switch( uMsg )
00081     {
00082         case WM_ERASEBKGND:
00083             return 1L;
00084 
00085         case WM_PAINT:
00086             PAINTSTRUCT ps;
00087             RECT pr;
00088             if( GetUpdateRect(hWnd, &pr, FALSE) )
00089             {
00090                 RECT bounds;
00091                 GetClientRect(hWnd, &bounds);
00092                 BeginPaint(hWnd, &ps);
00093                 p_instance->onPaint(ps.hdc, bounds, pr);
00094                 EndPaint(hWnd, &ps);
00095             }
00096             return 0L;
00097 
00098         default:
00099             return DefWindowProc(hWnd, uMsg, wParam, lParam);
00100     }
00101 };
00102 
00103 VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance) :
00104     _p_class_ref(p_class_ref),
00105     _hinstance(hInstance),
00106     _inplace_picture(NULL)
00107 {
00108     WNDCLASS wClass;
00109 
00110     if( ! GetClassInfo(hInstance, getInPlaceWndClassName(), &wClass) )
00111     {
00112         wClass.style          = CS_NOCLOSE|CS_DBLCLKS;
00113         wClass.lpfnWndProc    = VLCInPlaceClassWndProc;
00114         wClass.cbClsExtra     = 0;
00115         wClass.cbWndExtra     = 0;
00116         wClass.hInstance      = hInstance;
00117         wClass.hIcon          = NULL;
00118         wClass.hCursor        = LoadCursor(NULL, IDC_ARROW);
00119         wClass.hbrBackground  = NULL;
00120         wClass.lpszMenuName   = NULL;
00121         wClass.lpszClassName  = getInPlaceWndClassName();
00122        
00123         _inplace_wndclass_atom = RegisterClass(&wClass);
00124     }
00125     else
00126     {
00127         _inplace_wndclass_atom = 0;
00128     }
00129 
00130     if( ! GetClassInfo(hInstance, getVideoWndClassName(), &wClass) )
00131     {
00132         wClass.style          = CS_NOCLOSE;
00133         wClass.lpfnWndProc    = VLCVideoClassWndProc;
00134         wClass.cbClsExtra     = 0;
00135         wClass.cbWndExtra     = 0;
00136         wClass.hInstance      = hInstance;
00137         wClass.hIcon          = NULL;
00138         wClass.hCursor        = LoadCursor(NULL, IDC_ARROW);
00139         wClass.hbrBackground  = NULL;
00140         wClass.lpszMenuName   = NULL;
00141         wClass.lpszClassName  = getVideoWndClassName();
00142        
00143         _video_wndclass_atom = RegisterClass(&wClass);
00144     }
00145     else
00146     {
00147         _video_wndclass_atom = 0;
00148     }
00149 
00150     HBITMAP hbitmap = (HBITMAP)LoadImage(getHInstance(), TEXT("INPLACE-PICT"), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
00151     if( NULL != hbitmap )
00152     {
00153         PICTDESC pictDesc;
00154 
00155         pictDesc.cbSizeofstruct = sizeof(PICTDESC);
00156         pictDesc.picType        = PICTYPE_BITMAP;
00157         pictDesc.bmp.hbitmap    = hbitmap;
00158         pictDesc.bmp.hpal       = NULL;
00159 
00160         if( FAILED(OleCreatePictureIndirect(&pictDesc, IID_IPicture, TRUE, reinterpret_cast<LPVOID*>(&_inplace_picture))) )
00161             _inplace_picture = NULL;
00162     }
00163     AddRef();
00164 };
00165 
00166 VLCPluginClass::~VLCPluginClass()
00167 {
00168     if( 0 != _inplace_wndclass_atom )
00169         UnregisterClass(MAKEINTATOM(_inplace_wndclass_atom), _hinstance);
00170 
00171     if( 0 != _video_wndclass_atom )
00172         UnregisterClass(MAKEINTATOM(_video_wndclass_atom), _hinstance);
00173 
00174     if( NULL != _inplace_picture )
00175         _inplace_picture->Release();
00176 };
00177 
00178 STDMETHODIMP VLCPluginClass::QueryInterface(REFIID riid, void **ppv)
00179 {
00180     if( NULL == ppv )
00181         return E_INVALIDARG;
00182 
00183     if( (IID_IUnknown == riid) || (IID_IClassFactory == riid) )
00184     {
00185         AddRef();
00186         *ppv = reinterpret_cast<LPVOID>(this);
00187 
00188         return NOERROR;
00189     }
00190 
00191     *ppv = NULL;
00192 
00193     return E_NOINTERFACE;
00194 };
00195 
00196 STDMETHODIMP_(ULONG) VLCPluginClass::AddRef(void)
00197 {
00198     return InterlockedIncrement(_p_class_ref);
00199 };
00200 
00201 STDMETHODIMP_(ULONG) VLCPluginClass::Release(void)
00202 {
00203     ULONG refcount = InterlockedDecrement(_p_class_ref);
00204     if( 0 == refcount )
00205     {
00206         delete this;
00207         return 0;
00208     }
00209     return refcount;
00210 };
00211 
00212 STDMETHODIMP VLCPluginClass::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppv)
00213 {
00214     if( NULL == ppv )
00215         return E_POINTER;
00216 
00217     *ppv = NULL;
00218 
00219     if( (NULL != pUnkOuter) && (IID_IUnknown != riid) ) {
00220         return CLASS_E_NOAGGREGATION;
00221     }
00222 
00223     VLCPlugin *plugin = new VLCPlugin(this, pUnkOuter);
00224     if( NULL != plugin )
00225     {
00226         HRESULT hr = plugin->QueryInterface(riid, ppv);
00227         plugin->Release();
00228         return hr;
00229     }
00230     return E_OUTOFMEMORY;
00231 };
00232 
00233 STDMETHODIMP VLCPluginClass::LockServer(BOOL fLock)
00234 {
00235     if( fLock )
00236         AddRef();
00237     else 
00238         Release();
00239 
00240     return S_OK;
00241 };
00242 
00244 
00245 VLCPlugin::VLCPlugin(VLCPluginClass *p_class, LPUNKNOWN pUnkOuter) :
00246     _inplacewnd(NULL),
00247     _p_class(p_class),
00248     _i_ref(1UL),
00249     _i_codepage(CP_ACP),
00250     _b_usermode(TRUE),
00251     _bstr_mrl(NULL),
00252     _b_autoplay(TRUE),
00253     _b_autoloop(FALSE),
00254     _b_visible(TRUE),
00255     _b_mute(FALSE),
00256     _i_vlc(0)
00257 {
00258     p_class->AddRef();
00259 
00260     vlcOleControl = new VLCOleControl(this);
00261     vlcOleInPlaceObject = new VLCOleInPlaceObject(this);
00262     vlcOleInPlaceActiveObject = new VLCOleInPlaceActiveObject(this);
00263     vlcPersistStorage = new VLCPersistStorage(this);
00264     vlcPersistStreamInit = new VLCPersistStreamInit(this);
00265     vlcPersistPropertyBag = new VLCPersistPropertyBag(this);
00266     vlcProvideClassInfo = new VLCProvideClassInfo(this);
00267     vlcConnectionPointContainer = new VLCConnectionPointContainer(this);
00268     vlcObjectSafety = new VLCObjectSafety(this);
00269     vlcControl = new VLCControl(this);
00270     vlcViewObject = new VLCViewObject(this);
00271     vlcDataObject = new VLCDataObject(this);
00272     vlcOleObject = new VLCOleObject(this);
00273 
00274     // configure controlling IUnknown interface for implemented interfaces
00275     this->pUnkOuter = (NULL != pUnkOuter) ? pUnkOuter : dynamic_cast<LPUNKNOWN>(this);
00276 
00277     // default picure
00278     _p_pict = p_class->getInPlacePict();
00279 
00280     // set default/preferred size (320x240) pixels in HIMETRIC
00281     HDC hDC = CreateDevDC(NULL);
00282     _extent.cx = 320;
00283     _extent.cy = 240;
00284     HimetricFromDP(hDC, (LPPOINT)&_extent, 1);
00285     DeleteDC(hDC);
00286 };
00287 
00288 VLCPlugin::~VLCPlugin()
00289 {
00290     delete vlcOleObject;
00291     delete vlcDataObject;
00292     delete vlcViewObject;
00293     delete vlcControl;
00294     delete vlcConnectionPointContainer;
00295     delete vlcProvideClassInfo;
00296     delete vlcPersistPropertyBag;
00297     delete vlcPersistStreamInit;
00298     delete vlcPersistStorage;
00299     delete vlcOleInPlaceActiveObject;
00300     delete vlcOleInPlaceObject;
00301     delete vlcObjectSafety;
00302 
00303     delete vlcOleControl;
00304     if( _p_pict )
00305         _p_pict->Release();
00306 
00307     SysFreeString(_bstr_mrl);
00308 
00309     _p_class->Release();
00310 };
00311 
00312 STDMETHODIMP VLCPlugin::QueryInterface(REFIID riid, void **ppv)
00313 {
00314     if( NULL == ppv )
00315         return E_INVALIDARG;
00316 
00317     if( IID_IUnknown == riid )
00318         *ppv = reinterpret_cast<LPVOID>(this);
00319     else if( IID_IOleObject == riid )
00320         *ppv = reinterpret_cast<LPVOID>(vlcOleObject);
00321     else if( IID_IOleControl == riid )
00322         *ppv = reinterpret_cast<LPVOID>(vlcOleControl);
00323     else if( IID_IOleWindow == riid )
00324         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceObject);
00325     else if( IID_IOleInPlaceObject == riid )
00326         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceObject);
00327     else if( IID_IOleInPlaceActiveObject == riid )
00328         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceActiveObject);
00329     else if( IID_IPersist == riid )
00330         *ppv = reinterpret_cast<LPVOID>(vlcPersistStreamInit);
00331     else if( IID_IPersistStreamInit == riid )
00332         *ppv = reinterpret_cast<LPVOID>(vlcPersistStreamInit);
00333     else if( IID_IPersistStorage == riid )
00334         *ppv = reinterpret_cast<LPVOID>(vlcPersistStorage);
00335     else if( IID_IPersistPropertyBag == riid )
00336         *ppv = reinterpret_cast<LPVOID>(vlcPersistPropertyBag);
00337     else if( IID_IProvideClassInfo == riid )
00338         *ppv = reinterpret_cast<LPVOID>(vlcProvideClassInfo);
00339     else if( IID_IProvideClassInfo2 == riid )
00340         *ppv = reinterpret_cast<LPVOID>(vlcProvideClassInfo);
00341     else if( IID_IConnectionPointContainer == riid )
00342         *ppv = reinterpret_cast<LPVOID>(vlcConnectionPointContainer);
00343     else if( IID_IObjectSafety == riid )
00344         *ppv = reinterpret_cast<LPVOID>(vlcObjectSafety);
00345     else if( IID_IDispatch == riid )
00346         *ppv = reinterpret_cast<LPVOID>(vlcControl);
00347     else if( IID_IVLCControl == riid )
00348         *ppv = reinterpret_cast<LPVOID>(vlcControl);
00349     else if( IID_IViewObject == riid )
00350         *ppv = reinterpret_cast<LPVOID>(vlcViewObject);
00351     else if( IID_IViewObject2 == riid )
00352         *ppv = reinterpret_cast<LPVOID>(vlcViewObject);
00353     else if( IID_IDataObject == riid )
00354         *ppv = reinterpret_cast<LPVOID>(vlcDataObject);
00355     else
00356     {
00357         *ppv = NULL;
00358         return E_NOINTERFACE;
00359     }
00360     ((LPUNKNOWN)*ppv)->AddRef();
00361     return NOERROR;
00362 };
00363 
00364 STDMETHODIMP_(ULONG) VLCPlugin::AddRef(void)
00365 {
00366     return InterlockedIncrement((LONG *)&_i_ref);
00367 };
00368 
00369 STDMETHODIMP_(ULONG) VLCPlugin::Release(void)
00370 {
00371     if( ! InterlockedDecrement((LONG *)&_i_ref) )
00372     {
00373         delete this;
00374         return 0;
00375     }
00376     return _i_ref;
00377 };
00378 
00380 
00381 /*
00382 ** we use a window to represent plugin viewport,
00383 ** whose geometry is limited by the clipping rectangle
00384 ** all drawing within this window must follow must
00385 ** follow coordinates system described in lprPosRect
00386 */
00387 
00388 static void getViewportCoords(LPRECT lprPosRect, LPRECT lprClipRect)
00389 {
00390     RECT bounds;
00391     bounds.right  = lprPosRect->right-lprPosRect->left;
00392 
00393     if( lprClipRect->left <= lprPosRect->left )
00394     {
00395         // left side is not clipped out
00396         bounds.left = 0;
00397 
00398         if( lprClipRect->right >= lprPosRect->right )
00399         {
00400             // right side is not clipped out, no change
00401         }
00402         else if( lprClipRect->right >= lprPosRect->left )
00403         {
00404             // right side is clipped out
00405             lprPosRect->right = lprClipRect->right;
00406         }
00407         else
00408         {
00409             // outside of clipping rectange, not visible
00410             lprPosRect->right = lprPosRect->left;
00411         }
00412     }
00413     else
00414     {
00415         // left side is clipped out
00416         bounds.left = lprPosRect->left-lprClipRect->left;
00417         bounds.right += bounds.left;
00418 
00419         lprPosRect->left = lprClipRect->left;
00420         if( lprClipRect->right >= lprPosRect->right )
00421         {
00422             // right side is not clipped out
00423         }
00424         else
00425         {
00426             // right side is clipped out
00427             lprPosRect->right = lprClipRect->right;
00428         }
00429     }
00430 
00431     bounds.bottom = lprPosRect->bottom-lprPosRect->top;
00432 
00433     if( lprClipRect->top <= lprPosRect->top )
00434     {
00435         // top side is not clipped out
00436         bounds.top = 0;
00437 
00438         if( lprClipRect->bottom >= lprPosRect->bottom )
00439         {
00440             // bottom side is not clipped out, no change
00441         }
00442         else if( lprClipRect->bottom >= lprPosRect->top )
00443         {
00444             // bottom side is clipped out
00445             lprPosRect->bottom = lprClipRect->bottom;
00446         }
00447         else
00448         {
00449             // outside of clipping rectange, not visible
00450             lprPosRect->right = lprPosRect->left;
00451         }
00452     }
00453     else
00454     {
00455         bounds.top = lprPosRect->top-lprClipRect->top;
00456         bounds.bottom += bounds.top;
00457 
00458         lprPosRect->top = lprClipRect->top;
00459         if( lprClipRect->bottom >= lprPosRect->bottom )
00460         {
00461             // bottom side is not clipped out
00462         }
00463         else
00464         {
00465             // bottom side is clipped out
00466             lprPosRect->bottom = lprClipRect->bottom;
00467         }
00468     }
00469     *lprClipRect = *lprPosRect;
00470     *lprPosRect  = bounds;
00471 };
00472 
00473 HRESULT VLCPlugin::onInit(void)
00474 {
00475     if( 0 == _i_vlc )
00476     {
00477         _i_vlc = VLC_Create();
00478         if( _i_vlc < 0 )
00479         {
00480             _i_vlc = 0;
00481             return E_FAIL;
00482         }
00483 
00484         /*
00485         ** default initialization options
00486         */
00487         char *ppsz_argv[10] = { "vlc", "-vv", "--no-one-instance" };
00488         int   ppsz_argc = 3;
00489 
00490         HKEY h_key;
00491         DWORD i_type, i_data = MAX_PATH + 1;
00492         char p_data[MAX_PATH + 1];
00493         if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, "Software\\VideoLAN\\VLC",
00494                           0, KEY_READ, &h_key ) == ERROR_SUCCESS )
00495         {
00496              if( RegQueryValueEx( h_key, "InstallDir", 0, &i_type,
00497                                   (LPBYTE)p_data, &i_data ) == ERROR_SUCCESS )
00498              {
00499                  if( i_type == REG_SZ )
00500                  {
00501                      strcat( p_data, "\\vlc" );
00502                      ppsz_argv[0] = p_data;
00503                  }
00504              }
00505              RegCloseKey( h_key );
00506         }
00507 
00508 #if 0
00509         ppsz_argv[0] = "C:\\cygwin\\home\\Damien_Fouilleul\\dev\\videolan\\vlc-trunk\\vlc";
00510 #endif
00511 
00512         if( IsDebuggerPresent() )
00513         {
00514             /*
00515             ** VLC default threading mechanism is designed to be as compatible
00516             ** with POSIX as possible, however when debugged on win32, threads
00517             ** lose signals and eventually VLC get stuck during initialization.
00518             ** threading support can be configured to be more debugging friendly
00519             ** but it will be less compatible with POSIX.
00520             ** This is done by initializing with the following options
00521             */
00522             ppsz_argv[ppsz_argc++] = "--fast-mutex";
00523             ppsz_argv[ppsz_argc++] = "--win9x-cv-method=1";
00524         }
00525 
00526         if( VLC_Init(_i_vlc, ppsz_argc, ppsz_argv) )
00527         {
00528             VLC_Destroy(_i_vlc);
00529             _i_vlc = 0;
00530             return E_FAIL;
00531         }
00532         return S_OK;
00533     }
00534     return CO_E_ALREADYINITIALIZED;
00535 };
00536 
00537 HRESULT VLCPlugin::onLoad(void)
00538 {
00539     if( _b_mute )
00540         VLC_VolumeMute(_i_vlc);
00541 
00542     if( SysStringLen(_bstr_mrl) > 0 )
00543     {
00544         /*
00545         ** try to combine MRL with client site moniker, which for Internet Explorer
00546         ** is the URL of the page the plugin is embedded into. Hence, if the MRL
00547         ** is a relative URL, we should end up with an absolute URL
00548         */
00549         IOleClientSite *pClientSite;
00550         if( SUCCEEDED(vlcOleObject->GetClientSite(&pClientSite)) && (NULL != pClientSite) )
00551         {
00552             IBindCtx *pBC = 0;
00553             if( SUCCEEDED(CreateBindCtx(0, &pBC)) )
00554             {
00555                 LPMONIKER pContMoniker = NULL;
00556                 if( SUCCEEDED(pClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
00557                                 OLEWHICHMK_CONTAINER, &pContMoniker)) )
00558                 {
00559                     LPOLESTR base_url;
00560                     if( SUCCEEDED(pContMoniker->GetDisplayName(pBC, NULL, &base_url)) )
00561                     {
00562                         /*
00563                         ** check that the moniker name is a URL
00564                         */
00565                         if( UrlIsW(base_url, URLIS_URL) )
00566                         {
00567                             DWORD len = INTERNET_MAX_URL_LENGTH;
00568                             LPOLESTR abs_url = (LPOLESTR)CoTaskMemAlloc(sizeof(OLECHAR)*len);
00569                             if( NULL != abs_url )
00570                             {
00571                                 if( SUCCEEDED(UrlCombineW(base_url, _bstr_mrl, abs_url, &len,
00572                                                 URL_ESCAPE_UNSAFE|URL_PLUGGABLE_PROTOCOL)) )
00573                                 {
00574                                     SysFreeString(_bstr_mrl);
00575                                     _bstr_mrl = SysAllocStringLen(abs_url, len);
00576                                 }
00577                                 CoTaskMemFree(abs_url);
00578                             }
00579                         }
00580                         CoTaskMemFree(base_url);
00581                     }
00582                     pContMoniker->Release();
00583                 }
00584                 pBC->Release();
00585             }
00586             pClientSite->Release();
00587         }
00588 
00589         char *psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl);
00590         if( NULL != psz_mrl )
00591         {
00592             // add default target to playlist
00593             char *cOptions[1];
00594             int  cOptionsCount = 0;
00595 
00596             if( _b_autoloop )
00597             {
00598                 cOptions[cOptionsCount++] = "loop";
00599             }
00600             VLC_AddTarget(_i_vlc, psz_mrl, (const char **)&cOptions, cOptionsCount, PLAYLIST_APPEND, PLAYLIST_END);
00601             CoTaskMemFree(psz_mrl);
00602         }
00603     }
00604     setDirty(FALSE);
00605     return S_OK;
00606 };
00607 
00608 HRESULT VLCPlugin::onAmbientChanged(LPUNKNOWN pContainer, DISPID dispID)
00609 {
00610     VARIANT v;
00611     switch( dispID )
00612     {
00613         case DISPID_AMBIENT_BACKCOLOR:
00614             break;
00615         case DISPID_AMBIENT_DISPLAYNAME:
00616             break;
00617         case DISPID_AMBIENT_FONT:
00618             break;
00619         case DISPID_AMBIENT_FORECOLOR:
00620             break;
00621         case DISPID_AMBIENT_LOCALEID:
00622             break;
00623         case DISPID_AMBIENT_MESSAGEREFLECT:
00624             break;
00625         case DISPID_AMBIENT_SCALEUNITS:
00626             break;
00627         case DISPID_AMBIENT_TEXTALIGN:
00628             break;
00629         case DISPID_AMBIENT_USERMODE:
00630             VariantInit(&v);
00631             V_VT(&v) = VT_BOOL;
00632             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
00633             {
00634                 setUserMode(V_BOOL(&v) != VARIANT_FALSE);
00635             }
00636             break;
00637         case DISPID_AMBIENT_UIDEAD:
00638             break;
00639         case DISPID_AMBIENT_SHOWGRABHANDLES:
00640             break;
00641         case DISPID_AMBIENT_SHOWHATCHING:
00642             break;
00643         case DISPID_AMBIENT_DISPLAYASDEFAULT:
00644             break;
00645         case DISPID_AMBIENT_SUPPORTSMNEMONICS:
00646             break;
00647         case DISPID_AMBIENT_AUTOCLIP:
00648             break;
00649         case DISPID_AMBIENT_APPEARANCE:
00650             break;
00651         case DISPID_AMBIENT_CODEPAGE:
00652             VariantInit(&v);
00653             V_VT(&v) = VT_I4;
00654             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
00655             {
00656                 setCodePage(V_I4(&v));
00657             }
00658             break;
00659         case DISPID_AMBIENT_PALETTE:
00660             break;
00661         case DISPID_AMBIENT_CHARSET:
00662             break;
00663         case DISPID_AMBIENT_RIGHTTOLEFT:
00664             break;
00665         case DISPID_AMBIENT_TOPTOBOTTOM:
00666             break;
00667         case DISPID_UNKNOWN:
00668         /*
00669         ** multiple property change, look up the ones we are interested in
00670         */
00671             VariantInit(&v);
00672             V_VT(&v) = VT_BOOL;
00673             if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_USERMODE, v)) )
00674             {
00675                 setUserMode(V_BOOL(&v) != VARIANT_FALSE);
00676             }
00677             VariantInit(&v);
00678             V_VT(&v) = VT_I4;
00679             if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_CODEPAGE, v)) )
00680             {
00681                 setCodePage(V_I4(&v));
00682             }
00683             break;
00684     }
00685     return S_OK;
00686 };
00687 
00688 HRESULT VLCPlugin::onClose(DWORD dwSaveOption)
00689 {
00690     if( _i_vlc )
00691     {
00692         int i_vlc = _i_vlc;
00693 
00694         _i_vlc = 0;
00695         if( isInPlaceActive() )
00696         {
00697             onInPlaceDeactivate();
00698         }
00699         vlcDataObject->onClose();
00700 
00701         VLC_CleanUp(i_vlc);
00702         VLC_Destroy(i_vlc);
00703     }
00704     return S_OK;
00705 };
00706 
00707 BOOL VLCPlugin::isInPlaceActive(void)
00708 {
00709     return (NULL != _inplacewnd);
00710 };
00711 
00712 HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprcPosRect, LPCRECT lprcClipRect)
00713 {
00714     RECT posRect = *lprcPosRect;
00715     RECT clipRect = *lprcClipRect;
00716 
00717     /*
00718     ** record keeping of control geometry within container
00719     */ 
00720     _posRect = posRect;
00721 
00722     /*
00723     ** convert posRect & clipRect to match control viewport coordinates
00724     */
00725     getViewportCoords(&posRect, &clipRect);
00726 
00727     /*
00728     ** Create a window for in place activated control.
00729     ** the window geometry matches the control viewport
00730     ** within container so that embedded video is always
00731     ** properly clipped.
00732     */
00733     _inplacewnd = CreateWindow(_p_class->getInPlaceWndClassName(),
00734             "VLC Plugin In-Place Window",
00735             WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
00736             clipRect.left,
00737             clipRect.top,
00738             clipRect.right-clipRect.left,
00739             clipRect.bottom-clipRect.top,
00740             hwndParent,
00741             0,
00742             _p_class->getHInstance(),
00743             NULL
00744            );
00745 
00746     if( NULL == _inplacewnd )
00747         return E_FAIL;
00748 
00749     SetWindowLongPtr(_inplacewnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
00750 
00751     /*
00752     ** VLC embedded video automatically grows to cover client
00753     ** area of parent window.
00754     ** hence create a such a 'parent' window whose geometry
00755     ** is always correct relative to the viewport bounds
00756     */
00757     _videownd = CreateWindow(_p_class->getVideoWndClassName(),
00758             "VLC Plugin Video Window",
00759             WS_CHILD|WS_CLIPCHILDREN|WS_VISIBLE,
00760             posRect.left,
00761             posRect.top,
00762             posRect.right-posRect.left,
00763             posRect.bottom-posRect.top,
00764             _inplacewnd,
00765             0,
00766             _p_class->getHInstance(),
00767             NULL
00768            );
00769 
00770     if( NULL == _videownd )
00771     {
00772         DestroyWindow(_inplacewnd);
00773         return E_FAIL;
00774     }
00775 
00776     SetWindowLongPtr(_videownd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
00777 
00778     if( getVisible() )
00779         ShowWindow(_inplacewnd, SW_SHOWNORMAL);
00780 
00781     /* set internal video width and height */
00782     vlc_value_t val;
00783     val.i_int = posRect.right-posRect.left;
00784     VLC_VariableSet(_i_vlc, "conf::width", val);
00785     val.i_int = posRect.bottom-posRect.top;
00786     VLC_VariableSet(_i_vlc, "conf::height", val);
00787 
00788     /* set internal video parent window */
00789     /* horrible cast there */
00790     val.i_int = reinterpret_cast<int>(_videownd);
00791     VLC_VariableSet(_i_vlc, "drawable", val);
00792 
00793     if( _b_usermode && _b_autoplay & (VLC_PlaylistNumberOfItems(_i_vlc) > 0) )
00794     {
00795         VLC_Play(_i_vlc);
00796         fireOnPlayEvent();
00797     }
00798     return S_OK;
00799 };
00800 
00801 HRESULT VLCPlugin::onInPlaceDeactivate(void)
00802 {
00803     VLC_Stop(_i_vlc);
00804     fireOnStopEvent();
00805 
00806     DestroyWindow(_videownd);
00807     _videownd = NULL;
00808     DestroyWindow(_inplacewnd);
00809     _inplacewnd = NULL;
00810  
00811     return S_OK;
00812 };
00813 
00814 void VLCPlugin::setVisible(BOOL fVisible)
00815 {
00816     _b_visible = fVisible;
00817     if( isInPlaceActive() )
00818         ShowWindow(_inplacewnd, fVisible ? SW_SHOWNORMAL : SW_HIDE);
00819     firePropChangedEvent(DISPID_Visible);
00820 };
00821 
00822 void VLCPlugin::setFocus(BOOL fFocus)
00823 {
00824     if( fFocus )
00825         SetActiveWindow(_inplacewnd);
00826 };
00827 
00828 BOOL VLCPlugin::hasFocus(void)
00829 {
00830     return GetActiveWindow() == _inplacewnd;
00831 };
00832 
00833 void VLCPlugin::onDraw(DVTARGETDEVICE * ptd, HDC hicTargetDev,
00834         HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds)
00835 {
00836     if( getVisible() )
00837     {
00838         long width = lprcBounds->right-lprcBounds->left;
00839         long height = lprcBounds->bottom-lprcBounds->top;
00840 
00841         RECT bounds = { lprcBounds->left, lprcBounds->top, lprcBounds->right, lprcBounds->bottom };
00842         FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(WHITE_BRUSH));
00843 
00844         LPPICTURE pict = getPicture();
00845         if( NULL != pict )
00846         {
00847             OLE_XSIZE_HIMETRIC picWidth;
00848             OLE_YSIZE_HIMETRIC picHeight;
00849 
00850             pict->get_Width(&picWidth);
00851             pict->get_Height(&picHeight);
00852 
00853             SIZEL picSize = { picWidth, picHeight };
00854 
00855             if( NULL != hicTargetDev )
00856             {
00857                 DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1);
00858             }
00859             else if( NULL != (hicTargetDev = CreateDevDC(ptd)) )
00860             {
00861                 DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1);
00862                 DeleteDC(hicTargetDev);
00863             }
00864 
00865             if( picSize.cx > width-4 )
00866                 picSize.cx = width-4;
00867             if( picSize.cy > height-4 )
00868                 picSize.cy = height-4;
00869 
00870             LONG dstX = lprcBounds->left+(width-picSize.cx)/2;
00871             LONG dstY = lprcBounds->top+(height-picSize.cy)/2;
00872 
00873             if( NULL != lprcWBounds )
00874             {
00875                 RECT wBounds = { lprcWBounds->left, lprcWBounds->top, lprcWBounds->right, lprcWBounds->bottom };
00876                 pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy,
00877                         0L, picHeight, picWidth, -picHeight, &wBounds);
00878             }
00879             else 
00880                 pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy,
00881                         0L, picHeight, picWidth, -picHeight, NULL);
00882 
00883             pict->Release();
00884         }
00885 
00886         SelectObject(hdcDraw, GetStockObject(BLACK_BRUSH));
00887 
00888         MoveToEx(hdcDraw, bounds.left, bounds.top, NULL);
00889         LineTo(hdcDraw, bounds.left+width-1, bounds.top);
00890         LineTo(hdcDraw, bounds.left+width-1, bounds.top+height-1);
00891         LineTo(hdcDraw, bounds.left, bounds.top+height-1);
00892         LineTo(hdcDraw, bounds.left, bounds.top);
00893     }
00894 };
00895 
00896 void VLCPlugin::onPaint(HDC hdc, const RECT &bounds, const RECT &clipRect)
00897 {
00898     if( getVisible() )
00899     {
00902         HDC hdcDraw = CreateCompatibleDC(hdc);
00903         if( NULL != hdcDraw )
00904         {
00905             SIZEL size = getExtent();
00906             DPFromHimetric(hdc, (LPPOINT)&size, 1);
00907             RECTL posRect = { 0, 0, size.cx, size.cy };
00908 
00909             int width = bounds.right-bounds.left;
00910             int height = bounds.bottom-bounds.top;
00911 
00912             HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
00913             if( NULL != hBitmap )
00914             {
00915                 HBITMAP oldBmp = (HBITMAP)SelectObject(hdcDraw, hBitmap);
00916 
00917                 if( (size.cx != width) || (size.cy != height) )
00918                 {
00919                     // needs to scale canvas
00920                     SetMapMode(hdcDraw, MM_ANISOTROPIC);
00921                     SetWindowExtEx(hdcDraw, size.cx, size.cy, NULL);
00922                     SetViewportExtEx(hdcDraw, width, height, NULL);
00923                 }
00924 
00925                 onDraw(NULL, hdc, hdcDraw, &posRect, NULL);
00926 
00927                 SetMapMode(hdcDraw, MM_TEXT);
00928                 BitBlt(hdc, bounds.left, bounds.top,
00929                         width, height,
00930                         hdcDraw, 0, 0,
00931                         SRCCOPY);
00932 
00933                 SelectObject(hdcDraw, oldBmp);
00934                 DeleteObject(hBitmap);
00935             }
00936             DeleteDC(hdcDraw);
00937         }
00938     }
00939 };
00940 
00941 void VLCPlugin::onPositionChange(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
00942 {
00943     RECT clipRect = *lprcClipRect;
00944     RECT posRect  = *lprcPosRect;
00945 
00946     //RedrawWindow(GetParent(_inplacewnd), &_posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
00947 
00948     /*
00949     ** record keeping of control geometry within container
00950     */
00951     _posRect = posRect;
00952 
00953     /*
00954     ** convert posRect & clipRect to match control viewport coordinates
00955     */
00956     getViewportCoords(&posRect, &clipRect);
00957 
00958     /*
00959     ** change in-place window geometry to match clipping region
00960     */
00961     SetWindowPos(_inplacewnd, NULL,
00962             clipRect.left,
00963             clipRect.top,
00964             clipRect.right-clipRect.left,
00965             clipRect.bottom-clipRect.top,
00966             SWP_NOACTIVATE|
00967             SWP_NOCOPYBITS|
00968             SWP_NOZORDER|
00969             SWP_NOOWNERZORDER );
00970 
00971     /*
00972     ** change video window geometry to match object bounds within clipping region
00973     */
00974     SetWindowPos(_videownd, NULL,
00975             posRect.left,
00976             posRect.top,
00977             posRect.right-posRect.left,
00978             posRect.bottom-posRect.top,
00979             SWP_NOACTIVATE|
00980             SWP_NOCOPYBITS|
00981             SWP_NOZORDER|
00982             SWP_NOOWNERZORDER );
00983 
00984     //RedrawWindow(_videownd, &posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
00985     vlc_value_t val;
00986     val.i_int = posRect.right-posRect.left;
00987     VLC_VariableSet(_i_vlc, "conf::width", val);
00988     val.i_int = posRect.bottom-posRect.top;
00989     VLC_VariableSet(_i_vlc, "conf::height", val);
00990 };
00991 
00992 void VLCPlugin::freezeEvents(BOOL freeze)
00993 {
00994     vlcConnectionPointContainer->freezeEvents(freeze);
00995 };
00996 
00997 void VLCPlugin::firePropChangedEvent(DISPID dispid)
00998 {
00999     vlcConnectionPointContainer->firePropChangedEvent(dispid); 
01000 };
01001 
01002 void VLCPlugin::fireOnPlayEvent(void)
01003 {
01004     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
01005     vlcConnectionPointContainer->fireEvent(DISPID_PlayEvent, &dispparamsNoArgs); 
01006 };
01007 
01008 void VLCPlugin::fireOnPauseEvent(void)
01009 {
01010     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
01011     vlcConnectionPointContainer->fireEvent(DISPID_PauseEvent, &dispparamsNoArgs); 
01012 };
01013 
01014 void VLCPlugin::fireOnStopEvent(void)
01015 {
01016     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
01017     vlcConnectionPointContainer->fireEvent(DISPID_StopEvent, &dispparamsNoArgs); 
01018 };
01019 

Generated on Tue Dec 20 10:14:18 2005 for vlc-0.8.4a by  doxygen 1.4.2