home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / mac / SiteBldr / AMOVIE / SDK / _SETUP / COMMON.Z / ctlutil.h < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-29  |  24.8 KB  |  897 lines

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