plugin.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:32k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * plugin.cpp: ActiveX control for VLC
  3.  *****************************************************************************
  4.  * Copyright (C) 2006 the VideoLAN team
  5.  *
  6.  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  21.  *****************************************************************************/
  22. #include "plugin.h"
  23. #include "oleobject.h"
  24. #include "olecontrol.h"
  25. #include "oleinplaceobject.h"
  26. #include "oleinplaceactiveobject.h"
  27. #include "persistpropbag.h"
  28. #include "persiststreaminit.h"
  29. #include "persiststorage.h"
  30. #include "provideclassinfo.h"
  31. #include "connectioncontainer.h"
  32. #include "objectsafety.h"
  33. #include "vlccontrol.h"
  34. #include "vlccontrol2.h"
  35. #include "viewobject.h"
  36. #include "dataobject.h"
  37. #include "supporterrorinfo.h"
  38. #include "utils.h"
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <winreg.h>
  42. #include <winuser.h>
  43. #include <servprov.h>
  44. #include <shlwapi.h>
  45. #include <wininet.h>
  46. using namespace std;
  47. ////////////////////////////////////////////////////////////////////////
  48. //class factory
  49. static LRESULT CALLBACK VLCInPlaceClassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  50.     VLCPlugin *p_instance = reinterpret_cast<VLCPlugin *>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
  51.     switch( uMsg )
  52.     {
  53.         case WM_ERASEBKGND:
  54.             return 1L;
  55.         case WM_PAINT:
  56.             PAINTSTRUCT ps;
  57.             RECT pr;
  58.             if( GetUpdateRect(hWnd, &pr, FALSE) )
  59.             {
  60.                 RECT bounds;
  61.                 GetClientRect(hWnd, &bounds);
  62.                 BeginPaint(hWnd, &ps);
  63.                 p_instance->onPaint(ps.hdc, bounds, pr);
  64.                 EndPaint(hWnd, &ps);
  65.             }
  66.             return 0L;
  67.         default:
  68.             return DefWindowProc(hWnd, uMsg, wParam, lParam);
  69.     }
  70. };
  71. VLCPluginClass::VLCPluginClass(LONG *p_class_ref, HINSTANCE hInstance, REFCLSID rclsid) :
  72.     _p_class_ref(p_class_ref),
  73.     _hinstance(hInstance),
  74.     _classid(rclsid),
  75.     _inplace_picture(NULL)
  76. {
  77.     WNDCLASS wClass;
  78.     if( ! GetClassInfo(hInstance, getInPlaceWndClassName(), &wClass) )
  79.     {
  80.         wClass.style          = CS_NOCLOSE|CS_DBLCLKS;
  81.         wClass.lpfnWndProc    = VLCInPlaceClassWndProc;
  82.         wClass.cbClsExtra     = 0;
  83.         wClass.cbWndExtra     = 0;
  84.         wClass.hInstance      = hInstance;
  85.         wClass.hIcon          = NULL;
  86.         wClass.hCursor        = LoadCursor(NULL, IDC_ARROW);
  87.         wClass.hbrBackground  = NULL;
  88.         wClass.lpszMenuName   = NULL;
  89.         wClass.lpszClassName  = getInPlaceWndClassName();
  90.         _inplace_wndclass_atom = RegisterClass(&wClass);
  91.     }
  92.     else
  93.     {
  94.         _inplace_wndclass_atom = 0;
  95.     }
  96.     HBITMAP hbitmap = (HBITMAP)LoadImage(getHInstance(), MAKEINTRESOURCE(2), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
  97.     if( NULL != hbitmap )
  98.     {
  99.         PICTDESC pictDesc;
  100.         pictDesc.cbSizeofstruct = sizeof(PICTDESC);
  101.         pictDesc.picType        = PICTYPE_BITMAP;
  102.         pictDesc.bmp.hbitmap    = hbitmap;
  103.         pictDesc.bmp.hpal       = NULL;
  104.         if( FAILED(OleCreatePictureIndirect(&pictDesc, IID_IPicture, TRUE, reinterpret_cast<LPVOID*>(&_inplace_picture))) )
  105.             _inplace_picture = NULL;
  106.     }
  107.     AddRef();
  108. };
  109. VLCPluginClass::~VLCPluginClass()
  110. {
  111.     if( 0 != _inplace_wndclass_atom )
  112.         UnregisterClass(MAKEINTATOM(_inplace_wndclass_atom), _hinstance);
  113.     if( NULL != _inplace_picture )
  114.         _inplace_picture->Release();
  115. };
  116. STDMETHODIMP VLCPluginClass::QueryInterface(REFIID riid, void **ppv)
  117. {
  118.     if( NULL == ppv )
  119.         return E_INVALIDARG;
  120.     if( (IID_IUnknown == riid)
  121.      || (IID_IClassFactory == riid) )
  122.     {
  123.         AddRef();
  124.         *ppv = reinterpret_cast<LPVOID>(this);
  125.         return NOERROR;
  126.     }
  127.     *ppv = NULL;
  128.     return E_NOINTERFACE;
  129. };
  130. STDMETHODIMP_(ULONG) VLCPluginClass::AddRef(void)
  131. {
  132.     return InterlockedIncrement(_p_class_ref);
  133. };
  134. STDMETHODIMP_(ULONG) VLCPluginClass::Release(void)
  135. {
  136.     ULONG refcount = InterlockedDecrement(_p_class_ref);
  137.     if( 0 == refcount )
  138.     {
  139.         delete this;
  140.         return 0;
  141.     }
  142.     return refcount;
  143. };
  144. STDMETHODIMP VLCPluginClass::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, void **ppv)
  145. {
  146.     if( NULL == ppv )
  147.         return E_POINTER;
  148.     *ppv = NULL;
  149.     if( (NULL != pUnkOuter) && (IID_IUnknown != riid) ) {
  150.         return CLASS_E_NOAGGREGATION;
  151.     }
  152.     VLCPlugin *plugin = new VLCPlugin(this, pUnkOuter);
  153.     if( NULL != plugin )
  154.     {
  155.         HRESULT hr = plugin->QueryInterface(riid, ppv);
  156.         // the following will destroy the object if QueryInterface() failed
  157.         plugin->Release();
  158.         return hr;
  159.     }
  160.     return E_OUTOFMEMORY;
  161. };
  162. STDMETHODIMP VLCPluginClass::LockServer(BOOL fLock)
  163. {
  164.     if( fLock )
  165.         AddRef();
  166.     else
  167.         Release();
  168.     return S_OK;
  169. };
  170. ////////////////////////////////////////////////////////////////////////
  171. VLCPlugin::VLCPlugin(VLCPluginClass *p_class, LPUNKNOWN pUnkOuter) :
  172.     _inplacewnd(NULL),
  173.     _p_class(p_class),
  174.     _i_ref(1UL),
  175.     _p_libvlc(NULL),
  176.     _p_mlist(NULL),
  177.     _p_mplayer(NULL),
  178.     _i_midx(-1),
  179.     _i_codepage(CP_ACP),
  180.     _b_usermode(TRUE)
  181. {
  182.     p_class->AddRef();
  183.     vlcOleControl = new VLCOleControl(this);
  184.     vlcOleInPlaceObject = new VLCOleInPlaceObject(this);
  185.     vlcOleInPlaceActiveObject = new VLCOleInPlaceActiveObject(this);
  186.     vlcPersistStorage = new VLCPersistStorage(this);
  187.     vlcPersistStreamInit = new VLCPersistStreamInit(this);
  188.     vlcPersistPropertyBag = new VLCPersistPropertyBag(this);
  189.     vlcProvideClassInfo = new VLCProvideClassInfo(this);
  190.     vlcConnectionPointContainer = new VLCConnectionPointContainer(this);
  191.     vlcObjectSafety = new VLCObjectSafety(this);
  192.     vlcControl = new VLCControl(this);
  193.     vlcControl2 = new VLCControl2(this);
  194.     vlcViewObject = new VLCViewObject(this);
  195.     vlcDataObject = new VLCDataObject(this);
  196.     vlcOleObject = new VLCOleObject(this);
  197.     vlcSupportErrorInfo = new VLCSupportErrorInfo(this);
  198.     // configure controlling IUnknown interface for implemented interfaces
  199.     this->pUnkOuter = (NULL != pUnkOuter) ? pUnkOuter : dynamic_cast<LPUNKNOWN>(this);
  200.     // default picure
  201.     _p_pict = p_class->getInPlacePict();
  202.     // make sure that persistable properties are initialized
  203.     onInit();
  204. };
  205. VLCPlugin::~VLCPlugin()
  206. {
  207.     /*
  208.     ** bump refcount to avoid recursive release from
  209.     ** following interfaces when releasing this interface
  210.     */
  211.     AddRef();
  212.     delete vlcSupportErrorInfo;
  213.     delete vlcOleObject;
  214.     delete vlcDataObject;
  215.     delete vlcViewObject;
  216.     delete vlcControl2;
  217.     delete vlcControl;
  218.     delete vlcConnectionPointContainer;
  219.     delete vlcProvideClassInfo;
  220.     delete vlcPersistPropertyBag;
  221.     delete vlcPersistStreamInit;
  222.     delete vlcPersistStorage;
  223.     delete vlcOleInPlaceActiveObject;
  224.     delete vlcOleInPlaceObject;
  225.     delete vlcObjectSafety;
  226.     delete vlcOleControl;
  227.     if( _p_pict )
  228.         _p_pict->Release();
  229.     SysFreeString(_bstr_mrl);
  230.     SysFreeString(_bstr_baseurl);
  231.     if( _p_mplayer ) { libvlc_media_player_release(_p_mplayer); _p_mplayer=NULL; }
  232.     if( _p_mlist )   { libvlc_media_list_release(_p_mlist); _p_mlist=NULL; }
  233.     if( _p_libvlc )  { libvlc_release(_p_libvlc); _p_libvlc=NULL; }
  234.     _p_class->Release();
  235. };
  236. STDMETHODIMP VLCPlugin::QueryInterface(REFIID riid, void **ppv)
  237. {
  238.     if( NULL == ppv )
  239.         return E_INVALIDARG;
  240.     if( IID_IUnknown == riid )
  241.         *ppv = reinterpret_cast<LPVOID>(this);
  242.     else if( IID_IOleObject == riid )
  243.         *ppv = reinterpret_cast<LPVOID>(vlcOleObject);
  244.     else if( IID_IOleControl == riid )
  245.         *ppv = reinterpret_cast<LPVOID>(vlcOleControl);
  246.     else if( IID_IOleWindow == riid )
  247.         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceObject);
  248.     else if( IID_IOleInPlaceObject == riid )
  249.         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceObject);
  250.     else if( IID_IOleInPlaceActiveObject == riid )
  251.         *ppv = reinterpret_cast<LPVOID>(vlcOleInPlaceActiveObject);
  252.     else if( IID_IPersist == riid )
  253.         *ppv = reinterpret_cast<LPVOID>(vlcPersistStreamInit);
  254.     else if( IID_IPersistStreamInit == riid )
  255.         *ppv = reinterpret_cast<LPVOID>(vlcPersistStreamInit);
  256.     else if( IID_IPersistStorage == riid )
  257.         *ppv = reinterpret_cast<LPVOID>(vlcPersistStorage);
  258.     else if( IID_IPersistPropertyBag == riid )
  259.         *ppv = reinterpret_cast<LPVOID>(vlcPersistPropertyBag);
  260.     else if( IID_IProvideClassInfo == riid )
  261.         *ppv = reinterpret_cast<LPVOID>(vlcProvideClassInfo);
  262.     else if( IID_IProvideClassInfo2 == riid )
  263.         *ppv = reinterpret_cast<LPVOID>(vlcProvideClassInfo);
  264.     else if( IID_IConnectionPointContainer == riid )
  265.         *ppv = reinterpret_cast<LPVOID>(vlcConnectionPointContainer);
  266.     else if( IID_IObjectSafety == riid )
  267.         *ppv = reinterpret_cast<LPVOID>(vlcObjectSafety);
  268.     else if( IID_IDispatch == riid )
  269.         *ppv = (CLSID_VLCPlugin2 == getClassID()) ?
  270.                 reinterpret_cast<LPVOID>(vlcControl2) :
  271.                 reinterpret_cast<LPVOID>(vlcControl);
  272.     else if( IID_IVLCControl == riid )
  273.         *ppv = reinterpret_cast<LPVOID>(vlcControl);
  274.     else if( IID_IVLCControl2 == riid )
  275.         *ppv = reinterpret_cast<LPVOID>(vlcControl2);
  276.     else if( IID_IViewObject == riid )
  277.         *ppv = reinterpret_cast<LPVOID>(vlcViewObject);
  278.     else if( IID_IViewObject2 == riid )
  279.         *ppv = reinterpret_cast<LPVOID>(vlcViewObject);
  280.     else if( IID_IDataObject == riid )
  281.         *ppv = reinterpret_cast<LPVOID>(vlcDataObject);
  282.     else if( IID_ISupportErrorInfo == riid )
  283.         *ppv = reinterpret_cast<LPVOID>(vlcSupportErrorInfo);
  284.     else
  285.     {
  286.         *ppv = NULL;
  287.         return E_NOINTERFACE;
  288.     }
  289.     ((LPUNKNOWN)*ppv)->AddRef();
  290.     return NOERROR;
  291. };
  292. STDMETHODIMP_(ULONG) VLCPlugin::AddRef(void)
  293. {
  294.     return InterlockedIncrement((LONG *)&_i_ref);
  295. };
  296. STDMETHODIMP_(ULONG) VLCPlugin::Release(void)
  297. {
  298.     if( ! InterlockedDecrement((LONG *)&_i_ref) )
  299.     {
  300.         delete this;
  301.         return 0;
  302.     }
  303.     return _i_ref;
  304. };
  305. //////////////////////////////////////
  306. HRESULT VLCPlugin::onInit(void)
  307. {
  308.     if( NULL == _p_libvlc )
  309.     {
  310.         // initialize persistable properties
  311.         _b_autoplay   = TRUE;
  312.         _b_autoloop   = FALSE;
  313.         _b_toolbar    = FALSE;
  314.         _bstr_baseurl = NULL;
  315.         _bstr_mrl     = NULL;
  316.         _b_visible    = TRUE;
  317.         _b_mute       = FALSE;
  318.         _i_volume     = 50;
  319.         _i_time       = 0;
  320.         _i_backcolor  = 0;
  321.         // set default/preferred size (320x240) pixels in HIMETRIC
  322.         HDC hDC = CreateDevDC(NULL);
  323.         _extent.cx = 320;
  324.         _extent.cy = 240;
  325.         HimetricFromDP(hDC, (LPPOINT)&_extent, 1);
  326.         DeleteDC(hDC);
  327.         return S_OK;
  328.     }
  329.     return CO_E_ALREADYINITIALIZED;
  330. };
  331. HRESULT VLCPlugin::onLoad(void)
  332. {
  333.     if( SysStringLen(_bstr_baseurl) == 0 )
  334.     {
  335.         /*
  336.         ** try to retreive the base URL using the client site moniker, which for Internet Explorer
  337.         ** is the URL of the page the plugin is embedded into.
  338.         */
  339.         LPOLECLIENTSITE pClientSite;
  340.         if( SUCCEEDED(vlcOleObject->GetClientSite(&pClientSite)) && (NULL != pClientSite) )
  341.         {
  342.             IBindCtx *pBC = 0;
  343.             if( SUCCEEDED(CreateBindCtx(0, &pBC)) )
  344.             {
  345.                 LPMONIKER pContMoniker = NULL;
  346.                 if( SUCCEEDED(pClientSite->GetMoniker(OLEGETMONIKER_ONLYIFTHERE,
  347.                                 OLEWHICHMK_CONTAINER, &pContMoniker)) )
  348.                 {
  349.                     LPOLESTR base_url;
  350.                     if( SUCCEEDED(pContMoniker->GetDisplayName(pBC, NULL, &base_url)) )
  351.                     {
  352.                         /*
  353.                         ** check that the moniker name is a URL
  354.                         */
  355.                         if( UrlIsW(base_url, URLIS_URL) )
  356.                         {
  357.                             /* copy base URL */
  358.                             _bstr_baseurl = SysAllocString(base_url);
  359.                         }
  360.                         CoTaskMemFree(base_url);
  361.                     }
  362.                 }
  363.             }
  364.         }
  365.     }
  366.     setDirty(FALSE);
  367.     return S_OK;
  368. };
  369. void VLCPlugin::initVLC()
  370. {
  371.     extern HMODULE DllGetModule();
  372.     /*
  373.     ** default initialization options
  374.     */
  375.     const char *ppsz_argv[32] = { };
  376.     int   ppsz_argc = 0;
  377.     char p_progpath[MAX_PATH];
  378.     {
  379.         TCHAR w_progpath[MAX_PATH];
  380.         DWORD len = GetModuleFileName(DllGetModule(), w_progpath, MAX_PATH);
  381.         if( len > 0 )
  382.         {
  383.             len = WideCharToMultiByte(CP_UTF8, 0, w_progpath, len, p_progpath,
  384.                        sizeof(p_progpath)-1, NULL, NULL);
  385.             if( len > 0 )
  386.             {
  387.                 p_progpath[len] = '';
  388.                 ppsz_argv[0] = p_progpath;
  389.             }
  390.         }
  391.     }
  392.     ppsz_argv[ppsz_argc++] = "-vv";
  393.     HKEY h_key;
  394.     char p_pluginpath[MAX_PATH];
  395.     if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("Software\VideoLAN\VLC"),
  396.                       0, KEY_READ, &h_key ) == ERROR_SUCCESS )
  397.     {
  398.         DWORD i_type, i_data = MAX_PATH;
  399.         TCHAR w_pluginpath[MAX_PATH];
  400.         if( RegQueryValueEx( h_key, TEXT("InstallDir"), 0, &i_type,
  401.                              (LPBYTE)w_pluginpath, &i_data ) == ERROR_SUCCESS )
  402.         {
  403.             if( i_type == REG_SZ )
  404.             {
  405.                 if( WideCharToMultiByte(CP_UTF8, 0, w_pluginpath, -1, p_pluginpath,
  406.                          sizeof(p_pluginpath)-sizeof("\plugins")+1, NULL, NULL) )
  407.                 {
  408.                     strcat( p_pluginpath, "\plugins" );
  409.                     ppsz_argv[ppsz_argc++] = "--plugin-path";
  410.                     ppsz_argv[ppsz_argc++] = p_pluginpath;
  411.                 }
  412.             }
  413.         }
  414.         RegCloseKey( h_key );
  415.     }
  416.     // make sure plugin isn't affected with VLC single instance mode
  417.     ppsz_argv[ppsz_argc++] = "--no-one-instance";
  418.     /* common settings */
  419.     ppsz_argv[ppsz_argc++] = "--no-stats";
  420.     ppsz_argv[ppsz_argc++] = "--no-media-library";
  421.     ppsz_argv[ppsz_argc++] = "--ignore-config";
  422.     ppsz_argv[ppsz_argc++] = "--intf=dummy";
  423.     // loop mode is a configuration option only
  424.     if( _b_autoloop )
  425.         ppsz_argv[ppsz_argc++] = "--loop";
  426.     libvlc_exception_t ex;
  427.     libvlc_exception_init(&ex);
  428.     _p_libvlc = libvlc_new(ppsz_argc, ppsz_argv, &ex);
  429.     if( libvlc_exception_raised(&ex) )
  430.         return;
  431.     _p_mlist = libvlc_media_list_new(_p_libvlc, &ex);
  432.     if( libvlc_exception_raised(&ex) )
  433.     {
  434.         libvlc_release(_p_libvlc);
  435.         return;
  436.     }
  437.     // initial volume setting
  438.     libvlc_audio_set_volume(_p_libvlc, _i_volume, NULL);
  439.     if( _b_mute )
  440.     {
  441.         libvlc_audio_set_mute(_p_libvlc, TRUE, NULL);
  442.     }
  443.     // initial playlist item
  444.     if( SysStringLen(_bstr_mrl) > 0 )
  445.     {
  446.         char *psz_mrl = NULL;
  447.         if( SysStringLen(_bstr_baseurl) > 0 )
  448.         {
  449.             /*
  450.             ** if the MRL a relative URL, we should end up with an absolute URL
  451.             */
  452.             LPWSTR abs_url = CombineURL(_bstr_baseurl, _bstr_mrl);
  453.             if( NULL != abs_url )
  454.             {
  455.                 psz_mrl = CStrFromWSTR(CP_UTF8, abs_url, wcslen(abs_url));
  456.                 CoTaskMemFree(abs_url);
  457.             }
  458.             else
  459.             {
  460.                 psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl);
  461.             }
  462.         }
  463.         else
  464.         {
  465.             /*
  466.             ** baseURL is empty, assume MRL is absolute
  467.             */
  468.             psz_mrl = CStrFromBSTR(CP_UTF8, _bstr_mrl);
  469.         }
  470.         if( NULL != psz_mrl )
  471.         {
  472.             const char *options[1];
  473.             int i_options = 0;
  474.             char timeBuffer[32];
  475.             if( _i_time )
  476.             {
  477.                 snprintf(timeBuffer, sizeof(timeBuffer), ":start-time=%d", _i_time);
  478.                 options[i_options++] = timeBuffer;
  479.             }
  480.             // add default target to playlist
  481.             playlist_add_extended_untrusted(psz_mrl, i_options, options, NULL);
  482.             CoTaskMemFree(psz_mrl);
  483.         }
  484.     }
  485. };
  486. void VLCPlugin::setErrorInfo(REFIID riid, const char *description)
  487. {
  488.     vlcSupportErrorInfo->setErrorInfo( getClassID() == CLSID_VLCPlugin2 ?
  489.         OLESTR("VideoLAN.VLCPlugin.2") : OLESTR("VideoLAN.VLCPlugin.1"),
  490.         riid, description );
  491. };
  492. HRESULT VLCPlugin::onAmbientChanged(LPUNKNOWN pContainer, DISPID dispID)
  493. {
  494.     VARIANT v;
  495.     switch( dispID )
  496.     {
  497.         case DISPID_AMBIENT_BACKCOLOR:
  498.             VariantInit(&v);
  499.             V_VT(&v) = VT_I4;
  500.             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
  501.             {
  502.                 setBackColor(V_I4(&v));
  503.             }
  504.             break;
  505.         case DISPID_AMBIENT_DISPLAYNAME:
  506.             break;
  507.         case DISPID_AMBIENT_FONT:
  508.             break;
  509.         case DISPID_AMBIENT_FORECOLOR:
  510.             break;
  511.         case DISPID_AMBIENT_LOCALEID:
  512.             break;
  513.         case DISPID_AMBIENT_MESSAGEREFLECT:
  514.             break;
  515.         case DISPID_AMBIENT_SCALEUNITS:
  516.             break;
  517.         case DISPID_AMBIENT_TEXTALIGN:
  518.             break;
  519.         case DISPID_AMBIENT_USERMODE:
  520.             VariantInit(&v);
  521.             V_VT(&v) = VT_BOOL;
  522.             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
  523.             {
  524.                 setUserMode(V_BOOL(&v) != VARIANT_FALSE);
  525.             }
  526.             break;
  527.         case DISPID_AMBIENT_UIDEAD:
  528.             break;
  529.         case DISPID_AMBIENT_SHOWGRABHANDLES:
  530.             break;
  531.         case DISPID_AMBIENT_SHOWHATCHING:
  532.             break;
  533.         case DISPID_AMBIENT_DISPLAYASDEFAULT:
  534.             break;
  535.         case DISPID_AMBIENT_SUPPORTSMNEMONICS:
  536.             break;
  537.         case DISPID_AMBIENT_AUTOCLIP:
  538.             break;
  539.         case DISPID_AMBIENT_APPEARANCE:
  540.             break;
  541.         case DISPID_AMBIENT_CODEPAGE:
  542.             VariantInit(&v);
  543.             V_VT(&v) = VT_I4;
  544.             if( SUCCEEDED(GetObjectProperty(pContainer, dispID, v)) )
  545.             {
  546.                 setCodePage(V_I4(&v));
  547.             }
  548.             break;
  549.         case DISPID_AMBIENT_PALETTE:
  550.             break;
  551.         case DISPID_AMBIENT_CHARSET:
  552.             break;
  553.         case DISPID_AMBIENT_RIGHTTOLEFT:
  554.             break;
  555.         case DISPID_AMBIENT_TOPTOBOTTOM:
  556.             break;
  557.         case DISPID_UNKNOWN:
  558.             /*
  559.             ** multiple property change, look up the ones we are interested in
  560.             */
  561.             VariantInit(&v);
  562.             V_VT(&v) = VT_BOOL;
  563.             if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_USERMODE, v)) )
  564.             {
  565.                 setUserMode(V_BOOL(&v) != VARIANT_FALSE);
  566.             }
  567.             VariantInit(&v);
  568.             V_VT(&v) = VT_I4;
  569.             if( SUCCEEDED(GetObjectProperty(pContainer, DISPID_AMBIENT_CODEPAGE, v)) )
  570.             {
  571.                 setCodePage(V_I4(&v));
  572.             }
  573.             break;
  574.     }
  575.     return S_OK;
  576. };
  577. HRESULT VLCPlugin::onClose(DWORD dwSaveOption)
  578. {
  579.     if( isInPlaceActive() )
  580.     {
  581.         onInPlaceDeactivate();
  582.     }
  583.     if( isRunning() )
  584.     {
  585.         libvlc_instance_t* p_libvlc = _p_libvlc;
  586.         IVLCLog *p_log;
  587.         if( SUCCEEDED(vlcControl2->get_log(&p_log)) )
  588.         {
  589.             // make sure the log is disabled
  590.             p_log->put_verbosity(-1);
  591.             p_log->Release();
  592.         }
  593.         _p_libvlc = NULL;
  594.         vlcDataObject->onClose();
  595.         if( p_libvlc )
  596.             libvlc_release(p_libvlc);
  597.     }
  598.     return S_OK;
  599. };
  600. BOOL VLCPlugin::isInPlaceActive(void)
  601. {
  602.     return (NULL != _inplacewnd);
  603. };
  604. HRESULT VLCPlugin::onActivateInPlace(LPMSG lpMesg, HWND hwndParent, LPCRECT lprcPosRect, LPCRECT lprcClipRect)
  605. {
  606.     RECT clipRect = *lprcClipRect;
  607.     libvlc_exception_t ex;
  608.     libvlc_exception_init(&ex);
  609.     /*
  610.     ** record keeping of control geometry within container
  611.     */
  612.     _posRect = *lprcPosRect;
  613.     /*
  614.     ** Create a window for in place activated control.
  615.     ** the window geometry matches the control viewport
  616.     ** within container so that embedded video is always
  617.     ** properly displayed.
  618.     */
  619.     _inplacewnd = CreateWindow(_p_class->getInPlaceWndClassName(),
  620.             TEXT("VLC Plugin In-Place Window"),
  621.             WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,
  622.             lprcPosRect->left,
  623.             lprcPosRect->top,
  624.             lprcPosRect->right-lprcPosRect->left,
  625.             lprcPosRect->bottom-lprcPosRect->top,
  626.             hwndParent,
  627.             0,
  628.             _p_class->getHInstance(),
  629.             NULL
  630.            );
  631.     if( NULL == _inplacewnd )
  632.         return E_FAIL;
  633.     SetWindowLongPtr(_inplacewnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
  634.     /* change cliprect coordinates system relative to window bounding rect */
  635.     OffsetRect(&clipRect, -lprcPosRect->left, -lprcPosRect->top);
  636.     HRGN clipRgn = CreateRectRgnIndirect(&clipRect);
  637.     SetWindowRgn(_inplacewnd, clipRgn, TRUE);
  638.     if( _b_usermode )
  639.     {
  640.         /* will run vlc if not done already */
  641.         libvlc_instance_t* p_libvlc;
  642.         HRESULT result = getVLC(&p_libvlc);
  643.         if( FAILED(result) )
  644.             return result;
  645.         /* set internal video width and height */
  646.         libvlc_video_set_size(p_libvlc,
  647.             lprcPosRect->right-lprcPosRect->left,
  648.             lprcPosRect->bottom-lprcPosRect->top,
  649.             NULL );
  650.         /* set internal video parent window */
  651.         libvlc_video_set_parent(p_libvlc,
  652.             reinterpret_cast<libvlc_drawable_t>(_inplacewnd), NULL);
  653.         if( _b_autoplay && playlist_select(0,NULL) )
  654.         {
  655.             libvlc_media_player_play(_p_mplayer,NULL);
  656.             fireOnPlayEvent();
  657.         }
  658.     }
  659.     if( isVisible() )
  660.         ShowWindow(_inplacewnd, SW_SHOW);
  661.     return S_OK;
  662. };
  663. HRESULT VLCPlugin::onInPlaceDeactivate(void)
  664. {
  665.     if( isPlaying(NULL) )
  666.     {
  667.         playlist_stop(NULL);
  668.         fireOnStopEvent();
  669.     }
  670.     DestroyWindow(_inplacewnd);
  671.     _inplacewnd = NULL;
  672.     return S_OK;
  673. };
  674. void VLCPlugin::setVisible(BOOL fVisible)
  675. {
  676.     if( fVisible != _b_visible )
  677.     {
  678.         _b_visible = fVisible;
  679.         if( isInPlaceActive() )
  680.         {
  681.             ShowWindow(_inplacewnd, fVisible ? SW_SHOW : SW_HIDE);
  682.             if( fVisible )
  683.                 InvalidateRect(_inplacewnd, NULL, TRUE);
  684.         }
  685.         setDirty(TRUE);
  686.         firePropChangedEvent(DISPID_Visible);
  687.     }
  688. };
  689. void VLCPlugin::setVolume(int volume)
  690. {
  691.     if( volume < 0 )
  692.         volume = 0;
  693.     else if( volume > 200 )
  694.         volume = 200;
  695.     if( volume != _i_volume )
  696.     {
  697.         _i_volume = volume;
  698.         if( isRunning() )
  699.         {
  700.             libvlc_audio_set_volume(_p_libvlc, _i_volume, NULL);
  701.         }
  702.         setDirty(TRUE);
  703.     }
  704. };
  705. void VLCPlugin::setBackColor(OLE_COLOR backcolor)
  706. {
  707.     if( _i_backcolor != backcolor )
  708.     {
  709.         _i_backcolor = backcolor;
  710.         if( isInPlaceActive() )
  711.         {
  712.         }
  713.         setDirty(TRUE);
  714.     }
  715. };
  716. void VLCPlugin::setTime(int seconds)
  717. {
  718.     if( seconds < 0 )
  719.         seconds = 0;
  720.     if( seconds != _i_time )
  721.     {
  722.         setStartTime(_i_time);
  723.         if( NULL != _p_mplayer )
  724.         {
  725.             libvlc_media_player_set_time(_p_mplayer, _i_time, NULL);
  726.         }
  727.     }
  728. };
  729. void VLCPlugin::setFocus(BOOL fFocus)
  730. {
  731.     if( fFocus )
  732.         SetActiveWindow(_inplacewnd);
  733. };
  734. BOOL VLCPlugin::hasFocus(void)
  735. {
  736.     return GetActiveWindow() == _inplacewnd;
  737. };
  738. void VLCPlugin::onDraw(DVTARGETDEVICE * ptd, HDC hicTargetDev,
  739.         HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds)
  740. {
  741.     if( isVisible() )
  742.     {
  743.         long width = lprcBounds->right-lprcBounds->left;
  744.         long height = lprcBounds->bottom-lprcBounds->top;
  745.         RECT bounds = { lprcBounds->left, lprcBounds->top, lprcBounds->right, lprcBounds->bottom };
  746.         if( isUserMode() )
  747.         {
  748.             /* VLC is in user mode, just draw background color */
  749.             COLORREF colorref = RGB(0, 0, 0);
  750.             OleTranslateColor(_i_backcolor, (HPALETTE)GetStockObject(DEFAULT_PALETTE), &colorref);
  751.             if( colorref != RGB(0, 0, 0) )
  752.             {
  753.                 /* custom background */
  754.                 HBRUSH colorbrush = CreateSolidBrush(colorref);
  755.                 FillRect(hdcDraw, &bounds, colorbrush);
  756.                 DeleteObject((HANDLE)colorbrush);
  757.             }
  758.             else
  759.             {
  760.                 /* black background */
  761.                 FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(BLACK_BRUSH));
  762.             }
  763.         }
  764.         else
  765.         {
  766.             /* VLC is in design mode, draw the VLC logo */
  767.             FillRect(hdcDraw, &bounds, (HBRUSH)GetStockObject(WHITE_BRUSH));
  768.             LPPICTURE pict = getPicture();
  769.             if( NULL != pict )
  770.             {
  771.                 OLE_XSIZE_HIMETRIC picWidth;
  772.                 OLE_YSIZE_HIMETRIC picHeight;
  773.                 pict->get_Width(&picWidth);
  774.                 pict->get_Height(&picHeight);
  775.                 SIZEL picSize = { picWidth, picHeight };
  776.                 if( NULL != hicTargetDev )
  777.                 {
  778.                     DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1);
  779.                 }
  780.                 else if( NULL != (hicTargetDev = CreateDevDC(ptd)) )
  781.                 {
  782.                     DPFromHimetric(hicTargetDev, (LPPOINT)&picSize, 1);
  783.                     DeleteDC(hicTargetDev);
  784.                 }
  785.                 if( picSize.cx > width-4 )
  786.                     picSize.cx = width-4;
  787.                 if( picSize.cy > height-4 )
  788.                     picSize.cy = height-4;
  789.                 LONG dstX = lprcBounds->left+(width-picSize.cx)/2;
  790.                 LONG dstY = lprcBounds->top+(height-picSize.cy)/2;
  791.                 if( NULL != lprcWBounds )
  792.                 {
  793.                     RECT wBounds = { lprcWBounds->left, lprcWBounds->top, lprcWBounds->right, lprcWBounds->bottom };
  794.                     pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy,
  795.                             0L, picHeight, picWidth, -picHeight, &wBounds);
  796.                 }
  797.                 else
  798.                     pict->Render(hdcDraw, dstX, dstY, picSize.cx, picSize.cy,
  799.                             0L, picHeight, picWidth, -picHeight, NULL);
  800.                 pict->Release();
  801.             }
  802.             SelectObject(hdcDraw, GetStockObject(BLACK_BRUSH));
  803.             MoveToEx(hdcDraw, bounds.left, bounds.top, NULL);
  804.             LineTo(hdcDraw, bounds.left+width-1, bounds.top);
  805.             LineTo(hdcDraw, bounds.left+width-1, bounds.top+height-1);
  806.             LineTo(hdcDraw, bounds.left, bounds.top+height-1);
  807.             LineTo(hdcDraw, bounds.left, bounds.top);
  808.         }
  809.     }
  810. };
  811. void VLCPlugin::onPaint(HDC hdc, const RECT &bounds, const RECT &clipRect)
  812. {
  813.     if( isVisible() )
  814.     {
  815.         /* if VLC is in design mode, draw control logo */
  816.         HDC hdcDraw = CreateCompatibleDC(hdc);
  817.         if( NULL != hdcDraw )
  818.         {
  819.             SIZEL size = getExtent();
  820.             DPFromHimetric(hdc, (LPPOINT)&size, 1);
  821.             RECTL posRect = { 0, 0, size.cx, size.cy };
  822.             int width = bounds.right-bounds.left;
  823.             int height = bounds.bottom-bounds.top;
  824.             HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
  825.             if( NULL != hBitmap )
  826.             {
  827.                 HBITMAP oldBmp = (HBITMAP)SelectObject(hdcDraw, hBitmap);
  828.                 if( (size.cx != width) || (size.cy != height) )
  829.                 {
  830.                     // needs to scale canvas
  831.                     SetMapMode(hdcDraw, MM_ANISOTROPIC);
  832.                     SetWindowExtEx(hdcDraw, size.cx, size.cy, NULL);
  833.                     SetViewportExtEx(hdcDraw, width, height, NULL);
  834.                 }
  835.                 onDraw(NULL, hdc, hdcDraw, &posRect, NULL);
  836.                 SetMapMode(hdcDraw, MM_TEXT);
  837.                 BitBlt(hdc, bounds.left, bounds.top,
  838.                         width, height,
  839.                         hdcDraw, 0, 0,
  840.                         SRCCOPY);
  841.                 SelectObject(hdcDraw, oldBmp);
  842.                 DeleteObject(hBitmap);
  843.             }
  844.             DeleteDC(hdcDraw);
  845.         }
  846.     }
  847. };
  848. void VLCPlugin::onPositionChange(LPCRECT lprcPosRect, LPCRECT lprcClipRect)
  849. {
  850.     RECT clipRect = *lprcClipRect;
  851.     //RedrawWindow(GetParent(_inplacewnd), &_posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
  852.     /*
  853.     ** record keeping of control geometry within container
  854.     */
  855.     _posRect = *lprcPosRect;
  856.     /*
  857.     ** change in-place window geometry to match clipping region
  858.     */
  859.     SetWindowPos(_inplacewnd, NULL,
  860.             lprcPosRect->left,
  861.             lprcPosRect->top,
  862.             lprcPosRect->right-lprcPosRect->left,
  863.             lprcPosRect->bottom-lprcPosRect->top,
  864.             SWP_NOACTIVATE|
  865.             SWP_NOCOPYBITS|
  866.             SWP_NOZORDER|
  867.             SWP_NOOWNERZORDER );
  868.     /* change cliprect coordinates system relative to window bounding rect */
  869.     OffsetRect(&clipRect, -lprcPosRect->left, -lprcPosRect->top);
  870.     HRGN clipRgn = CreateRectRgnIndirect(&clipRect);
  871.     SetWindowRgn(_inplacewnd, clipRgn, FALSE);
  872.     //RedrawWindow(_videownd, &posRect, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
  873.     if( isRunning() )
  874.     {
  875.         libvlc_video_set_size(_p_libvlc,
  876.             lprcPosRect->right-lprcPosRect->left,
  877.             lprcPosRect->bottom-lprcPosRect->top,
  878.             NULL );
  879.     }
  880. };
  881. void VLCPlugin::freezeEvents(BOOL freeze)
  882. {
  883.     vlcConnectionPointContainer->freezeEvents(freeze);
  884. };
  885. void VLCPlugin::firePropChangedEvent(DISPID dispid)
  886. {
  887.     vlcConnectionPointContainer->firePropChangedEvent(dispid);
  888. };
  889. void VLCPlugin::fireOnPlayEvent(void)
  890. {
  891.     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  892.     vlcConnectionPointContainer->fireEvent(DISPID_PlayEvent, &dispparamsNoArgs);
  893. };
  894. void VLCPlugin::fireOnPauseEvent(void)
  895. {
  896.     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  897.     vlcConnectionPointContainer->fireEvent(DISPID_PauseEvent, &dispparamsNoArgs);
  898. };
  899. void VLCPlugin::fireOnStopEvent(void)
  900. {
  901.     DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
  902.     vlcConnectionPointContainer->fireEvent(DISPID_StopEvent, &dispparamsNoArgs);
  903. };
  904. bool VLCPlugin::playlist_select( int idx, libvlc_exception_t *ex )
  905. {
  906.     libvlc_media_t *p_m = NULL;
  907.     libvlc_media_list_lock(_p_mlist);
  908.     int count = libvlc_media_list_count(_p_mlist,ex);
  909.     if( libvlc_exception_raised(ex) )
  910.         goto bad_unlock;
  911.     if( idx<0||idx>=count )
  912.         goto bad_unlock;
  913.     _i_midx = idx;
  914.     p_m = libvlc_media_list_item_at_index(_p_mlist,_i_midx,ex);
  915.     libvlc_media_list_unlock(_p_mlist);
  916.     if( libvlc_exception_raised(ex) )
  917.         return false;
  918.     if( _p_mplayer )
  919.     {
  920.         libvlc_media_player_release( _p_mplayer );
  921.         _p_mplayer = NULL;
  922.     }
  923.     _p_mplayer = libvlc_media_player_new_from_media(p_m,ex);
  924.     if( _p_mplayer )
  925.         set_player_window(ex);
  926.     libvlc_media_release( p_m );
  927.     return !libvlc_exception_raised(ex);
  928. bad_unlock:
  929.     libvlc_media_list_unlock(_p_mlist);
  930.     return false;
  931. }
  932. void VLCPlugin::set_player_window(libvlc_exception_t *ex)
  933. {
  934.     // XXX FIXME no idea if this is correct or not
  935.     libvlc_media_player_set_hwnd(_p_mplayer,getInPlaceWindow(),ex);
  936. }
  937. int  VLCPlugin::playlist_add_extended_untrusted(const char *mrl, int optc, const char **optv, libvlc_exception_t *ex)
  938. {
  939.     int item = -1;
  940.     libvlc_media_t *p_m = libvlc_media_new(_p_libvlc,mrl,ex);
  941.     if( libvlc_exception_raised(ex) )
  942.         return -1;
  943.     for( int i = 0; i < optc; ++i )
  944.     {
  945.         libvlc_media_add_option_untrusted(p_m, optv[i],ex);
  946.         if( libvlc_exception_raised(ex) )
  947.         {
  948.             libvlc_media_release(p_m);
  949.             return -1;
  950.         }
  951.     }
  952.     libvlc_media_list_lock(_p_mlist);
  953.     libvlc_media_list_add_media(_p_mlist,p_m,ex);
  954.     if( !libvlc_exception_raised(ex) )
  955.         item = libvlc_media_list_count(_p_mlist,ex)-1;
  956.     libvlc_media_list_unlock(_p_mlist);
  957.     libvlc_media_release(p_m);
  958.     return item;
  959. }