home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / BaseClasses / ctlutil.h < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  26.2 KB  |  920 lines

  1. //------------------------------------------------------------------------------
  2. // File: CtlUtil.h
  3. //
  4. // Desc: DirectShow base classes.
  5. //
  6. // Copyright (c) 1992-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9.  
  10. // Base classes implementing IDispatch parsing for the basic control dual
  11. // interfaces. Derive from these and implement just the custom method and
  12. // property methods. We also implement CPosPassThru that can be used by
  13. // renderers and transforms to pass by IMediaPosition and IMediaSeeking
  14.  
  15. #ifndef __CTLUTIL__
  16. #define __CTLUTIL__
  17.  
  18. // OLE Automation has different ideas of TRUE and FALSE
  19.  
  20. #define OATRUE (-1)
  21. #define OAFALSE (0)
  22.  
  23.  
  24. // It's possible that we could replace this class with CreateStdDispatch
  25.  
  26. class CBaseDispatch
  27. {
  28.     ITypeInfo * m_pti;
  29.  
  30. public:
  31.  
  32.     CBaseDispatch() : m_pti(NULL) {}
  33.     ~CBaseDispatch();
  34.  
  35.     /* IDispatch methods */
  36.     STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
  37.  
  38.     STDMETHODIMP GetTypeInfo(
  39.       REFIID riid,
  40.       UINT itinfo,
  41.       LCID lcid,
  42.       ITypeInfo ** pptinfo);
  43.  
  44.     STDMETHODIMP GetIDsOfNames(
  45.       REFIID riid,
  46.       OLECHAR  ** rgszNames,
  47.       UINT cNames,
  48.       LCID lcid,
  49.       DISPID * rgdispid);
  50. };
  51.  
  52.  
  53. class AM_NOVTABLE CMediaControl :
  54.     public IMediaControl,
  55.     public CUnknown
  56. {
  57.     CBaseDispatch m_basedisp;
  58.  
  59. public:
  60.  
  61.     CMediaControl(const TCHAR *, LPUNKNOWN);
  62.  
  63.     DECLARE_IUNKNOWN
  64.  
  65.     // override this to publicise our interfaces
  66.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  67.  
  68.     /* IDispatch methods */
  69.     STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
  70.  
  71.     STDMETHODIMP GetTypeInfo(
  72.       UINT itinfo,
  73.       LCID lcid,
  74.       ITypeInfo ** pptinfo);
  75.  
  76.     STDMETHODIMP GetIDsOfNames(
  77.       REFIID riid,
  78.       OLECHAR  ** rgszNames,
  79.       UINT cNames,
  80.       LCID lcid,
  81.       DISPID * rgdispid);
  82.  
  83.     STDMETHODIMP Invoke(
  84.       DISPID dispidMember,
  85.       REFIID riid,
  86.       LCID lcid,
  87.       WORD wFlags,
  88.       DISPPARAMS * pdispparams,
  89.       VARIANT * pvarResult,
  90.       EXCEPINFO * pexcepinfo,
  91.       UINT * puArgErr);
  92. };
  93.  
  94.  
  95. class AM_NOVTABLE CMediaEvent :
  96.     public IMediaEventEx,
  97.     public CUnknown
  98. {
  99.     CBaseDispatch m_basedisp;
  100.  
  101. public:
  102.  
  103.     CMediaEvent(const TCHAR *, LPUNKNOWN);
  104.  
  105.     DECLARE_IUNKNOWN
  106.  
  107.     // override this to publicise our interfaces
  108.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  109.  
  110.     /* IDispatch methods */
  111.     STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
  112.  
  113.     STDMETHODIMP GetTypeInfo(
  114.       UINT itinfo,
  115.       LCID lcid,
  116.       ITypeInfo ** pptinfo);
  117.  
  118.     STDMETHODIMP GetIDsOfNames(
  119.       REFIID riid,
  120.       OLECHAR  ** rgszNames,
  121.       UINT cNames,
  122.       LCID lcid,
  123.       DISPID * rgdispid);
  124.  
  125.     STDMETHODIMP Invoke(
  126.       DISPID dispidMember,
  127.       REFIID riid,
  128.       LCID lcid,
  129.       WORD wFlags,
  130.       DISPPARAMS * pdispparams,
  131.       VARIANT * pvarResult,
  132.       EXCEPINFO * pexcepinfo,
  133.       UINT * puArgErr);
  134. };
  135.  
  136.  
  137. class AM_NOVTABLE CMediaPosition :
  138.     public IMediaPosition,
  139.     public CUnknown
  140. {
  141.     CBaseDispatch m_basedisp;
  142.  
  143.  
  144. public:
  145.  
  146.     CMediaPosition(const TCHAR *, LPUNKNOWN);
  147.     CMediaPosition(const TCHAR *, LPUNKNOWN, HRESULT *phr);
  148.  
  149.     DECLARE_IUNKNOWN
  150.  
  151.     // override this to publicise our interfaces
  152.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  153.  
  154.     /* IDispatch methods */
  155.     STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
  156.  
  157.     STDMETHODIMP GetTypeInfo(
  158.       UINT itinfo,
  159.       LCID lcid,
  160.       ITypeInfo ** pptinfo);
  161.  
  162.     STDMETHODIMP GetIDsOfNames(
  163.       REFIID riid,
  164.       OLECHAR  ** rgszNames,
  165.       UINT cNames,
  166.       LCID lcid,
  167.       DISPID * rgdispid);
  168.  
  169.     STDMETHODIMP Invoke(
  170.       DISPID dispidMember,
  171.       REFIID riid,
  172.       LCID lcid,
  173.       WORD wFlags,
  174.       DISPPARAMS * pdispparams,
  175.       VARIANT * pvarResult,
  176.       EXCEPINFO * pexcepinfo,
  177.       UINT * puArgErr);
  178.  
  179. };
  180.  
  181.  
  182. // OA-compatibility means that we must use double as the RefTime value,
  183. // and REFERENCE_TIME (essentially a LONGLONG) within filters.
  184. // this class converts between the two
  185.  
  186. class COARefTime : public CRefTime {
  187. public:
  188.  
  189.     COARefTime() {
  190.     };
  191.  
  192.     COARefTime(CRefTime t)
  193.         : CRefTime(t)
  194.     {
  195.     };
  196.  
  197.     COARefTime(REFERENCE_TIME t)
  198.         : CRefTime(t)
  199.     {
  200.     };
  201.  
  202.     COARefTime(double d) {
  203.         m_time = (LONGLONG) (d * 10000000);
  204.     };
  205.  
  206.     operator double() {
  207.         return double(m_time) / 10000000;
  208.     };
  209.  
  210.     operator REFERENCE_TIME() {
  211.         return m_time;
  212.     };
  213.  
  214.     COARefTime& operator=(const double& rd)  {
  215.         m_time = (LONGLONG) (rd * 10000000);
  216.         return *this;
  217.     }
  218.  
  219.     COARefTime& operator=(const REFERENCE_TIME& rt)  {
  220.         m_time = rt;
  221.         return *this;
  222.     }
  223.  
  224.     inline BOOL operator==(const COARefTime& rt)
  225.     {
  226.         return m_time == rt.m_time;
  227.     };
  228.  
  229.     inline BOOL operator!=(const COARefTime& rt)
  230.     {
  231.         return m_time != rt.m_time;
  232.     };
  233.  
  234.     inline BOOL operator < (const COARefTime& rt)
  235.     {
  236.         return m_time < rt.m_time;
  237.     };
  238.  
  239.     inline BOOL operator > (const COARefTime& rt)
  240.     {
  241.         return m_time > rt.m_time;
  242.     };
  243.  
  244.     inline BOOL operator >= (const COARefTime& rt)
  245.     {
  246.         return m_time >= rt.m_time;
  247.     };
  248.  
  249.     inline BOOL operator <= (const COARefTime& rt)
  250.     {
  251.         return m_time <= rt.m_time;
  252.     };
  253.  
  254.     inline COARefTime operator+(const COARefTime& rt)
  255.     {
  256.         return COARefTime(m_time + rt.m_time);
  257.     };
  258.  
  259.     inline COARefTime operator-(const COARefTime& rt)
  260.     {
  261.         return COARefTime(m_time - rt.m_time);
  262.     };
  263.  
  264.     inline COARefTime operator*(LONG l)
  265.     {
  266.         return COARefTime(m_time * l);
  267.     };
  268.  
  269.     inline COARefTime operator/(LONG l)
  270.     {
  271.         return COARefTime(m_time / l);
  272.     };
  273.  
  274. private:
  275.     //  Prevent bugs from constructing from LONG (which gets
  276.     //  converted to double and then multiplied by 10000000
  277.     COARefTime(LONG);
  278.     operator=(LONG);
  279. };
  280.  
  281.  
  282. // A utility class that handles IMediaPosition and IMediaSeeking on behalf
  283. // of single-input pin renderers, or transform filters.
  284. //
  285. // Renderers will expose this from the filter; transform filters will
  286. // expose it from the output pin and not the renderer.
  287. //
  288. // Create one of these, giving it your IPin* for your input pin, and delegate
  289. // all IMediaPosition methods to it. It will query the input pin for
  290. // IMediaPosition and respond appropriately.
  291. //
  292. // Call ForceRefresh if the pin connection changes.
  293. //
  294. // This class no longer caches the upstream IMediaPosition or IMediaSeeking
  295. // it acquires it on each method call. This means ForceRefresh is not needed.
  296. // The method is kept for source compatibility and to minimise the changes
  297. // if we need to put it back later for performance reasons.
  298.  
  299. class CPosPassThru : public IMediaSeeking, public CMediaPosition
  300. {
  301.     IPin *m_pPin;
  302.  
  303.     HRESULT GetPeer(IMediaPosition **ppMP);
  304.     HRESULT GetPeerSeeking(IMediaSeeking **ppMS);
  305.  
  306. public:
  307.  
  308.     CPosPassThru(const TCHAR *, LPUNKNOWN, HRESULT*, IPin *);
  309.     DECLARE_IUNKNOWN
  310.  
  311.     HRESULT ForceRefresh() {
  312.         return S_OK;
  313.     };
  314.  
  315.     // override to return an accurate current position
  316.     virtual HRESULT GetMediaTime(LONGLONG *pStartTime,LONGLONG *pEndTime) {
  317.         return E_FAIL;
  318.     }
  319.  
  320.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,void **ppv);
  321.  
  322.     // IMediaSeeking methods
  323.     STDMETHODIMP GetCapabilities( DWORD * pCapabilities );
  324.     STDMETHODIMP CheckCapabilities( DWORD * pCapabilities );
  325.     STDMETHODIMP SetTimeFormat(const GUID * pFormat);
  326.     STDMETHODIMP GetTimeFormat(GUID *pFormat);
  327.     STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
  328.     STDMETHODIMP IsFormatSupported( const GUID * pFormat);
  329.     STDMETHODIMP QueryPreferredFormat( GUID *pFormat);
  330.     STDMETHODIMP ConvertTimeFormat(LONGLONG * pTarget, const GUID * pTargetFormat,
  331.                                    LONGLONG    Source, const GUID * pSourceFormat );
  332.     STDMETHODIMP SetPositions( LONGLONG * pCurrent, DWORD CurrentFlags
  333.                              , LONGLONG * pStop, DWORD StopFlags );
  334.  
  335.     STDMETHODIMP GetPositions( LONGLONG * pCurrent, LONGLONG * pStop );
  336.     STDMETHODIMP GetCurrentPosition( LONGLONG * pCurrent );
  337.     STDMETHODIMP GetStopPosition( LONGLONG * pStop );
  338.     STDMETHODIMP SetRate( double dRate);
  339.     STDMETHODIMP GetRate( double * pdRate);
  340.     STDMETHODIMP GetDuration( LONGLONG *pDuration);
  341.     STDMETHODIMP GetAvailable( LONGLONG *pEarliest, LONGLONG *pLatest );
  342.     STDMETHODIMP GetPreroll( LONGLONG *pllPreroll );
  343.  
  344.     // IMediaPosition properties
  345.     STDMETHODIMP get_Duration(REFTIME * plength);
  346.     STDMETHODIMP put_CurrentPosition(REFTIME llTime);
  347.     STDMETHODIMP get_StopTime(REFTIME * pllTime);
  348.     STDMETHODIMP put_StopTime(REFTIME llTime);
  349.     STDMETHODIMP get_PrerollTime(REFTIME * pllTime);
  350.     STDMETHODIMP put_PrerollTime(REFTIME llTime);
  351.     STDMETHODIMP get_Rate(double * pdRate);
  352.     STDMETHODIMP put_Rate(double dRate);
  353.     STDMETHODIMP get_CurrentPosition(REFTIME * pllTime);
  354.     STDMETHODIMP CanSeekForward(LONG *pCanSeekForward);
  355.     STDMETHODIMP CanSeekBackward(LONG *pCanSeekBackward);
  356.  
  357. private:
  358.     HRESULT GetSeekingLongLong( HRESULT (__stdcall IMediaSeeking::*pMethod)( LONGLONG * ),
  359.                                 LONGLONG * pll );
  360. };
  361.  
  362.  
  363. // Adds the ability to return a current position
  364.  
  365. class CRendererPosPassThru : public CPosPassThru
  366. {
  367.     CCritSec m_PositionLock;    // Locks access to our position
  368.     LONGLONG m_StartMedia;      // Start media time last seen
  369.     LONGLONG m_EndMedia;        // And likewise the end media
  370.     BOOL m_bReset;              // Have media times been set
  371.  
  372. public:
  373.  
  374.     // Used to help with passing media times through graph
  375.  
  376.     CRendererPosPassThru(const TCHAR *, LPUNKNOWN, HRESULT*, IPin *);
  377.     HRESULT RegisterMediaTime(IMediaSample *pMediaSample);
  378.     HRESULT RegisterMediaTime(LONGLONG StartTime,LONGLONG EndTime);
  379.     HRESULT GetMediaTime(LONGLONG *pStartTime,LONGLONG *pEndTime);
  380.     HRESULT ResetMediaTime();
  381.     HRESULT EOS();
  382. };
  383.  
  384. STDAPI CreatePosPassThru(
  385.     LPUNKNOWN pAgg,
  386.     BOOL bRenderer,
  387.     IPin *pPin,
  388.     IUnknown **ppPassThru
  389. );
  390.  
  391. // A class that handles the IDispatch part of IBasicAudio and leaves the
  392. // properties and methods themselves pure virtual.
  393.  
  394. class AM_NOVTABLE CBasicAudio : public IBasicAudio, public CUnknown
  395. {
  396.     CBaseDispatch m_basedisp;
  397.  
  398. public:
  399.  
  400.     CBasicAudio(const TCHAR *, LPUNKNOWN);
  401.  
  402.     DECLARE_IUNKNOWN
  403.  
  404.     // override this to publicise our interfaces
  405.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  406.  
  407.     /* IDispatch methods */
  408.     STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
  409.  
  410.     STDMETHODIMP GetTypeInfo(
  411.       UINT itinfo,
  412.       LCID lcid,
  413.       ITypeInfo ** pptinfo);
  414.  
  415.     STDMETHODIMP GetIDsOfNames(
  416.       REFIID riid,
  417.       OLECHAR  ** rgszNames,
  418.       UINT cNames,
  419.       LCID lcid,
  420.       DISPID * rgdispid);
  421.  
  422.     STDMETHODIMP Invoke(
  423.       DISPID dispidMember,
  424.       REFIID riid,
  425.       LCID lcid,
  426.       WORD wFlags,
  427.       DISPPARAMS * pdispparams,
  428.       VARIANT * pvarResult,
  429.       EXCEPINFO * pexcepinfo,
  430.       UINT * puArgErr);
  431. };
  432.  
  433.  
  434. // A class that handles the IDispatch part of IBasicVideo and leaves the
  435. // properties and methods themselves pure virtual.
  436.  
  437. class AM_NOVTABLE CBaseBasicVideo : public IBasicVideo2, public CUnknown
  438. {
  439.     CBaseDispatch m_basedisp;
  440.  
  441. public:
  442.  
  443.     CBaseBasicVideo(const TCHAR *, LPUNKNOWN);
  444.  
  445.     DECLARE_IUNKNOWN
  446.  
  447.     // override this to publicise our interfaces
  448.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  449.  
  450.     /* IDispatch methods */
  451.     STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
  452.  
  453.     STDMETHODIMP GetTypeInfo(
  454.       UINT itinfo,
  455.       LCID lcid,
  456.       ITypeInfo ** pptinfo);
  457.  
  458.     STDMETHODIMP GetIDsOfNames(
  459.       REFIID riid,
  460.       OLECHAR  ** rgszNames,
  461.       UINT cNames,
  462.       LCID lcid,
  463.       DISPID * rgdispid);
  464.  
  465.     STDMETHODIMP Invoke(
  466.       DISPID dispidMember,
  467.       REFIID riid,
  468.       LCID lcid,
  469.       WORD wFlags,
  470.       DISPPARAMS * pdispparams,
  471.       VARIANT * pvarResult,
  472.       EXCEPINFO * pexcepinfo,
  473.       UINT * puArgErr);
  474.  
  475.     STDMETHODIMP GetPreferredAspectRatio(
  476.       long *plAspectX,
  477.       long *plAspectY)
  478.     {
  479.         return E_NOTIMPL;
  480.     }
  481. };
  482.  
  483.  
  484. // A class that handles the IDispatch part of IVideoWindow and leaves the
  485. // properties and methods themselves pure virtual.
  486.  
  487. class AM_NOVTABLE CBaseVideoWindow : public IVideoWindow, public CUnknown
  488. {
  489.     CBaseDispatch m_basedisp;
  490.  
  491. public:
  492.  
  493.     CBaseVideoWindow(const TCHAR *, LPUNKNOWN);
  494.  
  495.     DECLARE_IUNKNOWN
  496.  
  497.     // override this to publicise our interfaces
  498.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  499.  
  500.     /* IDispatch methods */
  501.     STDMETHODIMP GetTypeInfoCount(UINT * pctinfo);
  502.  
  503.     STDMETHODIMP GetTypeInfo(
  504.       UINT itinfo,
  505.       LCID lcid,
  506.       ITypeInfo ** pptinfo);
  507.  
  508.     STDMETHODIMP GetIDsOfNames(
  509.       REFIID riid,
  510.       OLECHAR  ** rgszNames,
  511.       UINT cNames,
  512.       LCID lcid,
  513.       DISPID * rgdispid);
  514.  
  515.     STDMETHODIMP Invoke(
  516.       DISPID dispidMember,
  517.       REFIID riid,
  518.       LCID lcid,
  519.       WORD wFlags,
  520.       DISPPARAMS * pdispparams,
  521.       VARIANT * pvarResult,
  522.       EXCEPINFO * pexcepinfo,
  523.       UINT * puArgErr);
  524. };
  525.  
  526.  
  527. // abstract class to help source filters with their implementation
  528. // of IMediaPosition. Derive from this and set the duration (and stop
  529. // position). Also override NotifyChange to do something when the properties
  530. // change.
  531.  
  532. class AM_NOVTABLE CSourcePosition : public CMediaPosition
  533. {
  534.  
  535. public:
  536.     CSourcePosition(const TCHAR *, LPUNKNOWN, HRESULT*, CCritSec *);
  537.  
  538.     // IMediaPosition methods
  539.     STDMETHODIMP get_Duration(REFTIME * plength);
  540.     STDMETHODIMP put_CurrentPosition(REFTIME llTime);
  541.     STDMETHODIMP get_StopTime(REFTIME * pllTime);
  542.     STDMETHODIMP put_StopTime(REFTIME llTime);
  543.     STDMETHODIMP get_PrerollTime(REFTIME * pllTime);
  544.     STDMETHODIMP put_PrerollTime(REFTIME llTime);
  545.     STDMETHODIMP get_Rate(double * pdRate);
  546.     STDMETHODIMP put_Rate(double dRate);
  547.     STDMETHODIMP CanSeekForward(LONG *pCanSeekForward);
  548.     STDMETHODIMP CanSeekBackward(LONG *pCanSeekBackward);
  549.  
  550.     // override if you can return the data you are actually working on
  551.     STDMETHODIMP get_CurrentPosition(REFTIME * pllTime) {
  552.         return E_NOTIMPL;
  553.     };
  554.  
  555. protected:
  556.  
  557.     // we call this to notify changes. Override to handle them
  558.     virtual HRESULT ChangeStart() PURE;
  559.     virtual HRESULT ChangeStop() PURE;
  560.     virtual HRESULT ChangeRate() PURE;
  561.  
  562.     COARefTime m_Duration;
  563.     COARefTime m_Start;
  564.     COARefTime m_Stop;
  565.     double m_Rate;
  566.  
  567.     CCritSec * m_pLock;
  568. };
  569.  
  570. class AM_NOVTABLE CSourceSeeking :
  571.     public IMediaSeeking,
  572.     public CUnknown
  573. {
  574.  
  575. public:
  576.  
  577.     DECLARE_IUNKNOWN;
  578.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  579.  
  580.     // IMediaSeeking methods
  581.  
  582.     STDMETHODIMP IsFormatSupported(const GUID * pFormat);
  583.     STDMETHODIMP QueryPreferredFormat(GUID *pFormat);
  584.     STDMETHODIMP SetTimeFormat(const GUID * pFormat);
  585.     STDMETHODIMP IsUsingTimeFormat(const GUID * pFormat);
  586.     STDMETHODIMP GetTimeFormat(GUID *pFormat);
  587.     STDMETHODIMP GetDuration(LONGLONG *pDuration);
  588.     STDMETHODIMP GetStopPosition(LONGLONG *pStop);
  589.     STDMETHODIMP GetCurrentPosition(LONGLONG *pCurrent);
  590.     STDMETHODIMP GetCapabilities( DWORD * pCapabilities );
  591.     STDMETHODIMP CheckCapabilities( DWORD * pCapabilities );
  592.     STDMETHODIMP ConvertTimeFormat( LONGLONG * pTarget, const GUID * pTargetFormat,
  593.                                     LONGLONG    Source, const GUID * pSourceFormat );
  594.  
  595.     STDMETHODIMP SetPositions( LONGLONG * pCurrent,  DWORD CurrentFlags
  596.                  , LONGLONG * pStop,  DWORD StopFlags );
  597.  
  598.     STDMETHODIMP GetPositions( LONGLONG * pCurrent, LONGLONG * pStop );
  599.  
  600.     STDMETHODIMP GetAvailable( LONGLONG * pEarliest, LONGLONG * pLatest );
  601.     STDMETHODIMP SetRate( double dRate);
  602.     STDMETHODIMP GetRate( double * pdRate);
  603.     STDMETHODIMP GetPreroll(LONGLONG *pPreroll);
  604.  
  605.  
  606. protected:
  607.  
  608.     // ctor
  609.     CSourceSeeking(const TCHAR *, LPUNKNOWN, HRESULT*, CCritSec *);
  610.  
  611.     // we call this to notify changes. Override to handle them
  612.     virtual HRESULT ChangeStart() PURE;
  613.     virtual HRESULT ChangeStop() PURE;
  614.     virtual HRESULT ChangeRate() PURE;
  615.  
  616.     CRefTime m_rtDuration;      // length of stream
  617.     CRefTime m_rtStart;         // source will start here
  618.     CRefTime m_rtStop;          // source will stop here
  619.     double m_dRateSeeking;
  620.  
  621.     // seeking capabilities
  622.     DWORD m_dwSeekingCaps;
  623.  
  624.     CCritSec * m_pLock;
  625. };
  626.  
  627.  
  628. // Base classes supporting Deferred commands.
  629.  
  630. // Deferred commands are queued by calls to methods on the IQueueCommand
  631. // interface, exposed by the filtergraph and by some filters. A successful
  632. // call to one of these methods will return an IDeferredCommand interface
  633. // representing the queued command.
  634. //
  635. // A CDeferredCommand object represents a single deferred command, and exposes
  636. // the IDeferredCommand interface as well as other methods permitting time
  637. // checks and actual execution. It contains a reference to the CCommandQueue
  638. // object on which it is queued.
  639. //
  640. // CCommandQueue is a base class providing a queue of CDeferredCommand
  641. // objects, and methods to add, remove, check status and invoke the queued
  642. // commands. A CCommandQueue object would be part of an object that
  643. // implemented IQueueCommand.
  644.  
  645. class CCmdQueue;
  646.  
  647. // take a copy of the params and store them. Release any allocated
  648. // memory in destructor
  649.  
  650. class CDispParams : public DISPPARAMS
  651. {
  652. public:
  653.     CDispParams(UINT nArgs, VARIANT* pArgs, HRESULT *phr = NULL);
  654.     ~CDispParams();
  655. };
  656.  
  657.  
  658. // CDeferredCommand lifetime is controlled by refcounts. Caller of
  659. // InvokeAt.. gets a refcounted interface pointer, and the CCmdQueue
  660. // object also holds a refcount on us. Calling Cancel or Invoke takes
  661. // us off the CCmdQueue and thus reduces the refcount by 1. Once taken
  662. // off the queue we cannot be put back on the queue.
  663.  
  664. class CDeferredCommand
  665.     : public CUnknown,
  666.       public IDeferredCommand
  667. {
  668. public:
  669.  
  670.     CDeferredCommand(
  671.         CCmdQueue * pQ,
  672.         LPUNKNOWN   pUnk,               // aggregation outer unk
  673.         HRESULT *   phr,
  674.         LPUNKNOWN   pUnkExecutor,       // object that will execute this cmd
  675.         REFTIME     time,
  676.         GUID*       iid,
  677.         long        dispidMethod,
  678.         short       wFlags,
  679.         long        cArgs,
  680.         VARIANT*    pDispParams,
  681.         VARIANT*    pvarResult,
  682.         short*      puArgErr,
  683.         BOOL        bStream
  684.         );
  685.  
  686.     DECLARE_IUNKNOWN
  687.  
  688.     // override this to publicise our interfaces
  689.     STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
  690.  
  691.     // IDeferredCommand methods
  692.     STDMETHODIMP Cancel();
  693.     STDMETHODIMP Confidence(
  694.                     LONG* pConfidence);
  695.     STDMETHODIMP Postpone(
  696.                     REFTIME newtime);
  697.     STDMETHODIMP GetHResult(
  698.                     HRESULT* phrResult);
  699.  
  700.     // other public methods
  701.  
  702.     HRESULT Invoke();
  703.  
  704.     // access methods
  705.  
  706.     // returns TRUE if streamtime, FALSE if presentation time
  707.     BOOL IsStreamTime() {
  708.        return m_bStream;
  709.     };
  710.  
  711.     CRefTime GetTime() {
  712.         return m_time;
  713.     };
  714.  
  715.     REFIID GetIID() {
  716.         return *m_iid;
  717.     };
  718.  
  719.     long GetMethod() {
  720.         return m_dispidMethod;
  721.     };
  722.  
  723.     short GetFlags() {
  724.         return m_wFlags;
  725.     };
  726.  
  727.     DISPPARAMS* GetParams() {
  728.         return &m_DispParams;
  729.     };
  730.  
  731.     VARIANT* GetResult() {
  732.         return m_pvarResult;
  733.     };
  734.  
  735. protected:
  736.  
  737.     CCmdQueue* m_pQueue;
  738.  
  739.     // pUnk for the interface that we will execute the command on
  740.     LPUNKNOWN   m_pUnk;
  741.  
  742.     // stored command data
  743.     REFERENCE_TIME     m_time;
  744.     GUID*       m_iid;
  745.     long        m_dispidMethod;
  746.     short       m_wFlags;
  747.     VARIANT*    m_pvarResult;
  748.     BOOL        m_bStream;
  749.     CDispParams m_DispParams;
  750.     DISPID      m_DispId;         //  For get and put
  751.  
  752.     // we use this for ITypeInfo access
  753.     CBaseDispatch   m_Dispatch;
  754.  
  755.     // save retval here
  756.     HRESULT     m_hrResult;
  757. };
  758.  
  759.  
  760. // a list of CDeferredCommand objects. this is a base class providing
  761. // the basics of access to the list. If you want to use CDeferredCommand
  762. // objects then your queue needs to be derived from this class.
  763.  
  764. class AM_NOVTABLE CCmdQueue
  765. {
  766. public:
  767.     CCmdQueue();
  768.     virtual ~CCmdQueue();
  769.  
  770.     // returns a new CDeferredCommand object that will be initialised with
  771.     // the parameters and will be added to the queue during construction.
  772.     // returns S_OK if successfully created otherwise an error and
  773.     // no object has been queued.
  774.     virtual HRESULT  New(
  775.         CDeferredCommand **ppCmd,
  776.         LPUNKNOWN   pUnk,
  777.         REFTIME     time,
  778.         GUID*       iid,
  779.         long        dispidMethod,
  780.         short       wFlags,
  781.         long        cArgs,
  782.         VARIANT*    pDispParams,
  783.         VARIANT*    pvarResult,
  784.         short*      puArgErr,
  785.         BOOL        bStream
  786.     );
  787.  
  788.     // called by the CDeferredCommand object to add and remove itself
  789.     // from the queue
  790.     virtual HRESULT Insert(CDeferredCommand* pCmd);
  791.     virtual HRESULT Remove(CDeferredCommand* pCmd);
  792.  
  793.     // Command-Due Checking
  794.     //
  795.     // There are two schemes of synchronisation: coarse and accurate. In
  796.     // coarse mode, you wait till the time arrives and then execute the cmd.
  797.     // In accurate mode, you wait until you are processing the sample that
  798.     // will appear at the time, and then execute the command. It's up to the
  799.     // filter which one it will implement. The filtergraph will always
  800.     // implement coarse mode for commands queued at the filtergraph.
  801.     //
  802.     // If you want coarse sync, you probably want to wait until there is a
  803.     // command due, and then execute it. You can do this by calling
  804.     // GetDueCommand. If you have several things to wait for, get the
  805.     // event handle from GetDueHandle() and when this is signalled then call
  806.     // GetDueCommand. Stream time will only advance between calls to Run and
  807.     // EndRun. Note that to avoid an extra thread there is no guarantee that
  808.     // if the handle is set there will be a command ready. Each time the
  809.     // event is signalled, call GetDueCommand (probably with a 0 timeout);
  810.     // This may return E_ABORT.
  811.     //
  812.     // If you want accurate sync, you must call GetCommandDueFor, passing
  813.     // as a parameter the stream time of the samples you are about to process.
  814.     // This will return:
  815.     //   -- a stream-time command due at or before that stream time
  816.     //   -- a presentation-time command due at or before the
  817.     //      time that stream time will be presented (only between Run
  818.     //      and EndRun calls, since outside of this, the mapping from
  819.     //      stream time to presentation time is not known.
  820.     //   -- any presentation-time command due now.
  821.     // This means that if you want accurate synchronisation on samples that
  822.     // might be processed during Paused mode, you need to use
  823.     // stream-time commands.
  824.     //
  825.     // In all cases, commands remain queued until Invoked or Cancelled. The
  826.     // setting and resetting of the event handle is managed entirely by this
  827.     // queue object.
  828.  
  829.     // set the clock used for timing
  830.     virtual HRESULT SetSyncSource(IReferenceClock*);
  831.  
  832.     // switch to run mode. Streamtime to Presentation time mapping known.
  833.     virtual HRESULT Run(REFERENCE_TIME tStreamTimeOffset);
  834.  
  835.     // switch to Stopped or Paused mode. Time mapping not known.
  836.     virtual HRESULT EndRun();
  837.  
  838.     // return a pointer to the next due command. Blocks for msTimeout
  839.     // milliseconds until there is a due command.
  840.     // Stream-time commands will only become due between Run and Endrun calls.
  841.     // The command remains queued until invoked or cancelled.
  842.     // Returns E_ABORT if timeout occurs, otherwise S_OK (or other error).
  843.     // Returns an AddRef-ed object
  844.     virtual HRESULT GetDueCommand(CDeferredCommand ** ppCmd, long msTimeout);
  845.  
  846.     // return the event handle that will be signalled whenever
  847.     // there are deferred commands due for execution (when GetDueCommand
  848.     // will not block).
  849.     HANDLE GetDueHandle() {
  850.         return HANDLE(m_evDue);
  851.     };
  852.  
  853.     // return a pointer to a command that will be due for a given time.
  854.     // Pass in a stream time here. The stream time offset will be passed
  855.     // in via the Run method.
  856.     // Commands remain queued until invoked or cancelled.
  857.     // This method will not block. It will report VFW_E_NOT_FOUND if there
  858.     // are no commands due yet.
  859.     // Returns an AddRef-ed object
  860.     virtual HRESULT GetCommandDueFor(REFERENCE_TIME tStream, CDeferredCommand**ppCmd);
  861.  
  862.     // check if a given time is due (TRUE if it is due yet)
  863.     BOOL CheckTime(CRefTime time, BOOL bStream) {
  864.  
  865.         // if no clock, nothing is due!
  866.         if (!m_pClock) {
  867.             return FALSE;
  868.         }
  869.  
  870.         // stream time
  871.         if (bStream) {
  872.  
  873.             // not valid if not running
  874.             if (!m_bRunning) {
  875.                 return FALSE;
  876.             }
  877.             // add on known stream time offset to get presentation time
  878.             time += m_StreamTimeOffset;
  879.         }
  880.  
  881.         CRefTime Now;
  882.         m_pClock->GetTime((REFERENCE_TIME*)&Now);
  883.         return (time <= Now);
  884.     };
  885.  
  886. protected:
  887.  
  888.     // protect access to lists etc
  889.     CCritSec m_Lock;
  890.  
  891.     // commands queued in presentation time are stored here
  892.     CGenericList<CDeferredCommand> m_listPresentation;
  893.  
  894.     // commands queued in stream time are stored here
  895.     CGenericList<CDeferredCommand> m_listStream;
  896.  
  897.     // set when any commands are due
  898.     CAMEvent m_evDue;
  899.  
  900.     // creates an advise for the earliest time required, if any
  901.     void SetTimeAdvise(void);
  902.  
  903.     // advise id from reference clock (0 if no outstanding advise)
  904.     DWORD_PTR m_dwAdvise;
  905.  
  906.     // advise time is for this presentation time
  907.     CRefTime m_tCurrentAdvise;
  908.  
  909.     // the reference clock we are using (addrefed)
  910.     IReferenceClock* m_pClock;
  911.  
  912.     // true when running
  913.     BOOL m_bRunning;
  914.  
  915.     // contains stream time offset when m_bRunning is true
  916.     CRefTime m_StreamTimeOffset;
  917. };
  918.  
  919. #endif // __CTLUTIL__
  920.