1#pragma once
2
3//////////////////////////////////////////////////////////////////////////
4//  AsyncCallback [template]
5//
6//  Description:
7//  Helper class that routes IMFAsyncCallback::Invoke calls to a class
8//  method on the parent class.
9//
10//  Usage:
11//  Add this class as a member variable. In the parent class constructor,
12//  initialize the AsyncCallback class like this:
13//  	m_cb(this, &CYourClass::OnInvoke)
14//  where
15//      m_cb       = AsyncCallback object
16//      CYourClass = parent class
17//      OnInvoke   = Method in the parent class to receive Invoke calls.
18//
19//  The parent's OnInvoke method (you can name it anything you like) must
20//  have a signature that matches the InvokeFn typedef below.
21//////////////////////////////////////////////////////////////////////////
22
23// T: Type of the parent object
24template<class T>
25class AsyncCallback : public IMFAsyncCallback
26{
27public:
28    typedef HRESULT (T::*InvokeFn)(IMFAsyncResult *pAsyncResult);
29
30    AsyncCallback(T *pParent, InvokeFn fn) : m_pParent(pParent), m_pInvokeFn(fn)
31    {
32    }
33
34    // IUnknown
35    STDMETHODIMP_(ULONG) AddRef() {
36        // Delegate to parent class.
37        return m_pParent->AddRef();
38    }
39    STDMETHODIMP_(ULONG) Release() {
40        // Delegate to parent class.
41        return m_pParent->Release();
42    }
43    STDMETHODIMP QueryInterface(REFIID iid, void** ppv)
44    {
45        if (!ppv)
46        {
47            return E_POINTER;
48        }
49        if (iid == __uuidof(IUnknown))
50        {
51            *ppv = static_cast<IUnknown*>(static_cast<IMFAsyncCallback*>(this));
52        }
53        else if (iid == __uuidof(IMFAsyncCallback))
54        {
55            *ppv = static_cast<IMFAsyncCallback*>(this);
56        }
57        else
58        {
59            *ppv = NULL;
60            return E_NOINTERFACE;
61        }
62        AddRef();
63        return S_OK;
64    }
65
66
67    // IMFAsyncCallback methods
68    STDMETHODIMP GetParameters(DWORD*, DWORD*)
69    {
70        // Implementation of this method is optional.
71        return E_NOTIMPL;
72    }
73
74    STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult)
75    {
76        return (m_pParent->*m_pInvokeFn)(pAsyncResult);
77    }
78
79    T *m_pParent;
80    InvokeFn m_pInvokeFn;
81};
82