]> git.sesse.net Git - vlc/blobdiff - activex/connectioncontainer.cpp
input/meta.c: Don't re-run the art finder if the art was previously set in input_ArtF...
[vlc] / activex / connectioncontainer.cpp
index a18b0709da2597c67fd9d71e9d448353af82e77b..757f5139154175b1e8f0a5f08479c3060c248bb8 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * connectioncontainer.cpp: ActiveX control for VLC
  *****************************************************************************
- * Copyright (C) 2005 VideoLAN
+ * Copyright (C) 2005 the VideoLAN team
  *
  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
  *
@@ -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"
@@ -29,46 +29,64 @@ using namespace std;
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
-class VLCEnumConnections : public IEnumConnections
+/* this function object is used to return the value from a map pair */
+struct VLCEnumConnectionsDereference
 {
-public:
-    VLCEnumConnections(vector<CONNECTDATA> &v) :
-        e(VLCEnum<CONNECTDATA>(IID_IEnumConnections, v))
-    { e.setRetainOperation((VLCEnum<CONNECTDATA>::retainer)&retain); };
-
-    VLCEnumConnections(const VLCEnumConnections &vlcEnum) : e(vlcEnum.e) {};
-
-    virtual ~VLCEnumConnections() {};
-
-    // IUnknown methods
-    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
-        { return e.QueryInterface(riid, ppv); };
-    STDMETHODIMP_(ULONG) AddRef(void)
-        { return e.AddRef(); };
-    STDMETHODIMP_(ULONG) Release(void)
-        {return e.Release(); };
-
-    //IEnumConnectionPoints
-    STDMETHODIMP Next(ULONG celt, LPCONNECTDATA rgelt, ULONG *pceltFetched)
-        { return e.Next(celt, rgelt, pceltFetched); };
-    STDMETHODIMP Skip(ULONG celt)
-        { return e.Skip(celt);};
-    STDMETHODIMP Reset(void)
-        { return e.Reset();};
-    STDMETHODIMP Clone(LPENUMCONNECTIONS *ppenum)
-        { if( NULL == ppenum ) return E_POINTER;
-          *ppenum = dynamic_cast<LPENUMCONNECTIONS>(new VLCEnumConnections(*this));
-          return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
-        };
-
-private:
-
-    static void retain(CONNECTDATA cd)
+    CONNECTDATA operator()(const map<DWORD,LPUNKNOWN>::iterator& i)
     {
-        cd.pUnk->AddRef();
+        CONNECTDATA cd;
+
+        i->second->AddRef();
+
+        cd.dwCookie = i->first;
+        cd.pUnk     = i->second;
+        return cd;
     };
+};
+
+class VLCEnumConnections : public VLCEnumIterator<IID_IEnumConnections,
+    IEnumConnections,
+    CONNECTDATA,
+    map<DWORD,LPUNKNOWN>::iterator,
+    VLCEnumConnectionsDereference>
+{
+public:
+    VLCEnumConnections(map<DWORD,LPUNKNOWN> &m) :
+        VLCEnumIterator<IID_IEnumConnections,
+            IEnumConnections,
+            CONNECTDATA,
+            map<DWORD,LPUNKNOWN>::iterator,
+            VLCEnumConnectionsDereference> (m.begin(), m.end())
+    {};
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+
+/* this function object is used to retain the dereferenced iterator value */
+struct VLCEnumConnectionPointsDereference
+{
+    LPCONNECTIONPOINT operator()(const vector<LPCONNECTIONPOINT>::iterator& i)
+    {
+        LPCONNECTIONPOINT cp = *i;
+        cp->AddRef();
+        return cp;
+    }
+};
 
-    VLCEnum<CONNECTDATA> e;
+class VLCEnumConnectionPoints: public VLCEnumIterator<IID_IEnumConnectionPoints,
+    IEnumConnectionPoints,
+    LPCONNECTIONPOINT,
+    vector<LPCONNECTIONPOINT>::iterator,
+    VLCEnumConnectionPointsDereference>
+{
+public:
+    VLCEnumConnectionPoints(vector<LPCONNECTIONPOINT>& v) :
+        VLCEnumIterator<IID_IEnumConnectionPoints,
+            IEnumConnectionPoints,
+            LPCONNECTIONPOINT,
+            vector<LPCONNECTIONPOINT>::iterator,
+            VLCEnumConnectionPointsDereference> (v.begin(), v.end())
+    {};
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
@@ -94,31 +112,29 @@ STDMETHODIMP VLCConnectionPoint::GetConnectionPointContainer(LPCONNECTIONPOINTCO
 
 STDMETHODIMP VLCConnectionPoint::Advise(IUnknown *pUnk, DWORD *pdwCookie)
 {
+    static DWORD dwCookieCounter = 0;
+
     if( (NULL == pUnk) || (NULL == pdwCookie) )
         return E_POINTER;
 
-    CONNECTDATA cd;
-
-    pUnk->AddRef();
-    cd.pUnk = pUnk;
-    *pdwCookie = cd.dwCookie = _connections.size();
-
-    _connections.push_back(cd);
-
-    return S_OK;
+    if( SUCCEEDED(pUnk->QueryInterface(_iid, (LPVOID *)&pUnk)) )
+    {
+        *pdwCookie = ++dwCookieCounter;
+        _connections[*pdwCookie] = pUnk;
+        return S_OK;
+    }
+    return CONNECT_E_CANNOTCONNECT;
 };
 
 STDMETHODIMP VLCConnectionPoint::Unadvise(DWORD pdwCookie)
 {
-    if( pdwCookie < _connections.size() )
+    map<DWORD,LPUNKNOWN>::iterator pcd = _connections.find((DWORD)pdwCookie);
+    if( pcd != _connections.end() )
     {
-        CONNECTDATA cd = _connections[pdwCookie];
-        if( NULL != cd.pUnk )
-        {
-            cd.pUnk->Release();
-            cd.pUnk = NULL;
-            return S_OK;
-        }
+        pcd->second->Release();
+
+        _connections.erase(pdwCookie);
+        return S_OK;
     }
     return CONNECT_E_NOCONNECTION;
 };
@@ -133,18 +149,18 @@ STDMETHODIMP VLCConnectionPoint::EnumConnections(IEnumConnections **ppEnum)
     return (NULL != *ppEnum ) ? S_OK : E_OUTOFMEMORY;
 };
 
-void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMSpDispParams)
+void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS *pDispParams)
 {
-    vector<CONNECTDATA>::iterator end = _connections.end();
-    vector<CONNECTDATA>::iterator iter = _connections.begin();
+    map<DWORD,LPUNKNOWN>::iterator end = _connections.end();
+    map<DWORD,LPUNKNOWN>::iterator iter = _connections.begin();
 
     while( iter != end )
     {
-        CONNECTDATA cd = *iter;
-        if( NULL != cd.pUnk )
+        LPUNKNOWN pUnk = iter->second;
+        if( NULL != pUnk )
         {
             IDispatch *pDisp;
-            if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IDispatch, (LPVOID *)&pDisp)) )
+            if( SUCCEEDED(pUnk->QueryInterface(_iid, (LPVOID *)&pDisp)) )
             {
                 pDisp->Invoke(dispId, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, pDispParams, NULL, NULL, NULL);
                 pDisp->Release();
@@ -156,16 +172,16 @@ void VLCConnectionPoint::fireEvent(DISPID dispId, DISPPARAMS* pDispParams)
 
 void VLCConnectionPoint::firePropChangedEvent(DISPID dispId)
 {
-    vector<CONNECTDATA>::iterator end = _connections.end();
-    vector<CONNECTDATA>::iterator iter = _connections.begin();
+    map<DWORD,LPUNKNOWN>::iterator end = _connections.end();
+    map<DWORD,LPUNKNOWN>::iterator iter = _connections.begin();
 
     while( iter != end )
     {
-        CONNECTDATA cd = *iter;
-        if( NULL != cd.pUnk )
+        LPUNKNOWN pUnk = iter->second;
+        if( NULL != pUnk )
         {
             IPropertyNotifySink *pPropSink;
-            if( SUCCEEDED(cd.pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) )
+            if( SUCCEEDED(pUnk->QueryInterface(IID_IPropertyNotifySink, (LPVOID *)&pPropSink)) )
             {
                 pPropSink->OnChanged(dispId);
                 pPropSink->Release();
@@ -177,52 +193,23 @@ void VLCConnectionPoint::firePropChangedEvent(DISPID dispId)
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
-class VLCEnumConnectionPoints : public IEnumConnectionPoints
+VLCDispatchEvent::~VLCDispatchEvent()
 {
-public:
-    VLCEnumConnectionPoints(vector<LPCONNECTIONPOINT> &v) :
-        e(VLCEnum<LPCONNECTIONPOINT>(IID_IEnumConnectionPoints, v))
-    { e.setRetainOperation((VLCEnum<LPCONNECTIONPOINT>::retainer)&retain); };
-
-    VLCEnumConnectionPoints(const VLCEnumConnectionPoints &vlcEnum) : e(vlcEnum.e) {};
-
-    virtual ~VLCEnumConnectionPoints() {};
-
-    // IUnknown methods
-    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
-        { return e.QueryInterface(riid, ppv); };
-    STDMETHODIMP_(ULONG) AddRef(void)
-        { return e.AddRef(); };
-    STDMETHODIMP_(ULONG) Release(void)
-        {return e.Release(); };
-
-    //IEnumConnectionPoints
-    STDMETHODIMP Next(ULONG celt, LPCONNECTIONPOINT *rgelt, ULONG *pceltFetched)
-        { return e.Next(celt, rgelt, pceltFetched); };
-    STDMETHODIMP Skip(ULONG celt)
-        { return e.Skip(celt);};
-    STDMETHODIMP Reset(void)
-        { return e.Reset();};
-    STDMETHODIMP Clone(LPENUMCONNECTIONPOINTS *ppenum)
-        { if( NULL == ppenum ) return E_POINTER;
-          *ppenum = dynamic_cast<LPENUMCONNECTIONPOINTS>(new VLCEnumConnectionPoints(*this));
-          return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
-        };
-
-private:
-
-    static void retain(LPCONNECTIONPOINT cp)
+    //clear event arguments
+    if( NULL != _dispParams.rgvarg )
     {
-        cp->AddRef();
-    };
-
-    VLCEnum<LPCONNECTIONPOINT> e;
+        for(unsigned int c=0; c<_dispParams.cArgs; ++c)
+            VariantClear(_dispParams.rgvarg+c);
+        CoTaskMemFree(_dispParams.rgvarg);
+    }
+    if( NULL != _dispParams.rgdispidNamedArgs )
+        CoTaskMemFree(_dispParams.rgdispidNamedArgs);
 };
 
 ////////////////////////////////////////////////////////////////////////////////////////////////
 
 VLCConnectionPointContainer::VLCConnectionPointContainer(VLCPlugin *p_instance) :
-    _p_instance(p_instance)
+    _p_instance(p_instance), _b_freeze(FALSE)
 {
     _p_events = new VLCConnectionPoint(dynamic_cast<LPCONNECTIONPOINTCONTAINER>(this),
             _p_instance->getDispEventID());
@@ -237,7 +224,6 @@ VLCConnectionPointContainer::VLCConnectionPointContainer(VLCPlugin *p_instance)
 
 VLCConnectionPointContainer::~VLCConnectionPointContainer()
 {
-    _v_cps.clear();
     delete _p_props;
     delete _p_events;
 };
@@ -275,13 +261,44 @@ STDMETHODIMP VLCConnectionPointContainer::FindConnectionPoint(REFIID riid, IConn
     return NOERROR;
 };
 
+void VLCConnectionPointContainer::freezeEvents(BOOL freeze)
+{
+    if( ! freeze )
+    {
+        // release queued events
+        while( ! _q_events.empty() )
+        {
+            VLCDispatchEvent *ev = _q_events.front();
+            _q_events.pop();
+            _p_events->fireEvent(ev->_dispId, &ev->_dispParams);
+            delete ev;
+        }
+    }
+    _b_freeze = freeze;
+};
+
 void VLCConnectionPointContainer::fireEvent(DISPID dispId, DISPPARAMS* pDispParams)
 {
-    _p_events->fireEvent(dispId, pDispParams);
+    if( _b_freeze )
+    {
+        // queue event for later use when container is ready
+        _q_events.push(new VLCDispatchEvent(dispId, *pDispParams));
+        if( _q_events.size() > 10 )
+        {
+            // too many events in queue, get rid of older one
+            delete _q_events.front();
+            _q_events.pop();
+        }
+    }
+    else
+    {
+        _p_events->fireEvent(dispId, pDispParams);
+    }
 };
 
 void VLCConnectionPointContainer::firePropChangedEvent(DISPID dispId)
 {
-    _p_props->firePropChangedEvent(dispId);
+    if( ! _b_freeze )
+        _p_props->firePropChangedEvent(dispId);
 };