/*++ Copyright (c) Microsoft Corporation. All rights reserved. Module Name: MSPStrm.h Abstract: Definitions for CMSPStream class. --*/ #ifndef _MSPSTRM_H_ #define _MSPSTRM_H_ /*++ Class Description: Represents a stream in a call. --*/ #define STRM_INITIAL 0x00000000 #define STRM_TERMINALSELECTED 0x00000001 #define STRM_CONFIGURED 0x00000002 #define STRM_RUNNING 0x00000004 #define STRM_PAUSED 0x00000008 #define STRM_STOPPED 0x00000010 class CMSPStream; class ATL_NO_VTABLE CPTEventSink : public CComObjectRootEx, public ITPluggableTerminalEventSink { public: CPTEventSink(); ~CPTEventSink(); BEGIN_COM_MAP( CPTEventSink ) COM_INTERFACE_ENTRY( ITPluggableTerminalEventSink ) END_COM_MAP() public: // --- ITDTEventSink --- STDMETHOD(FireEvent)( /* in */ const MSP_EVENT_INFO *pMspEventInfo ); public: // // set the stream which will be processing our events // // this method is called by the stream when it creates and initializes // the sink object, and also when the stream is going away and want to // tell us that it is no longer available to process our events. // HRESULT SetSinkStream( CMSPStream *pStream ); private: // // a nested structure that is used to pass event and stream to the // asynchronous event processing routine. // struct AsyncEventStruct { // // pointer to the stream on which to fire event // CMSPStream *pMSPStream; // // pointer to the event item to be processed // MSPEVENTITEM *pEventItem; // // as a public service, initialize structure's data members // AsyncEventStruct() :pMSPStream(NULL), pEventItem(NULL) { LOG((MSP_TRACE, "AsyncEventStruct::AsyncEventStruct[%p]", this)); } // // as a safety measure, set data members to NULL's in destructor // to make sure no one attemopts to use them after the strcuture is // gone. // // note: we don't free any data members here -- that's responsibility // of the structure's client // ~AsyncEventStruct() { pMSPStream = NULL; pEventItem = NULL; LOG((MSP_TRACE, "AsyncEventStruct::~AsyncEventStruct[%p]", this)); } }; // AsyncEventStruct // // the callback function that is submitted to thread pool api for async // event processing. The argument is the event structure containing stream // and the actual event // static DWORD WINAPI FireEventCallBack(LPVOID pEventStructure); private: CMSPStream* m_pMSPStream; }; class ATL_NO_VTABLE CMSPStream : public CComObjectRootEx, public IDispatchImpl { public: BEGIN_COM_MAP(CMSPStream) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(ITStream) COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pFTM) END_COM_MAP() DECLARE_GET_CONTROLLING_UNKNOWN() CMSPStream(); ~CMSPStream(); // methods of the CComObject virtual void FinalRelease(); // ITStream methods, called by the app. STDMETHOD (get_MediaType) ( OUT long * plMediaType ); STDMETHOD (get_Direction) ( OUT TERMINAL_DIRECTION * pTerminalDirection ); STDMETHOD (get_Name) ( OUT BSTR * ppName ) = 0; STDMETHOD (SelectTerminal) ( IN ITTerminal * pTerminal ); STDMETHOD (UnselectTerminal) ( IN ITTerminal * pTerminal ); STDMETHOD (EnumerateTerminals) ( OUT IEnumTerminal ** ppEnumTerminal ); STDMETHOD (get_Terminals) ( OUT VARIANT * pTerminals ); STDMETHOD (StartStream) (); STDMETHOD (PauseStream) (); STDMETHOD (StopStream) (); // methods called by the MSPCall object. virtual HRESULT Init( IN HANDLE hAddress, IN CMSPCallBase * pMSPCall, IN IMediaEvent * pGraph, IN DWORD dwMediaType, IN TERMINAL_DIRECTION Direction ); virtual HRESULT ShutDown(); virtual HRESULT GetState( OUT DWORD * pdwStatus ) { return E_NOTIMPL; } virtual HRESULT HandleTSPData( IN BYTE * pData, IN DWORD dwSize ); virtual HRESULT ProcessGraphEvent( IN long lEventCode, IN LONG_PTR lParam1, IN LONG_PTR lParam2 ); protected: // --- Helper functions --- HRESULT RegisterPluggableTerminalEventSink( /*[in]*/ ITTerminal* pTerminal ); HRESULT UnregisterPluggableTerminalEventSink( /*[in]*/ ITTerminal* pTerminal ); HRESULT ReleaseSink(); // // we want to have control over our addref and release logic: we need to do // special tricks to avoid stream being accessed by the event sink while // the stream is being deleted. // ULONG InternalAddRef(); ULONG InternalRelease(); public: // // this method is called by CPTEventSink when it has an event for us to // process // HRESULT HandleSinkEvent(MSPEVENTITEM *pEventItem); protected: // Pointer to the free threaded marshaler. IUnknown * m_pFTM; // The current state of the stream. DWORD m_dwState; // The media type of this stream. Audio, video, or others. DWORD m_dwMediaType; // The direction of this stream. Incoming or outgoing. TERMINAL_DIRECTION m_Direction; // The address on which this stream is being used. HANDLE m_hAddress; // The reference to the call object. CMSPCallBase * m_pMSPCall; // The pointers to the graph object interfaces. IGraphBuilder * m_pIGraphBuilder; IMediaControl * m_pIMediaControl; // The list of stream objects in the call. CMSPArray m_Terminals; // The lock that protects the stream object. The stream object // should never acquire the lock and then call a MSPCall method // that might lock. CMSPCritSection m_lock; // The lock that protects refcounting on the stream object. this is a // workaround needed to sync against event sink attempting to access the // stream object while it is being deleted. CMSPCritSection m_lockRefCount; // The Event Sink for pluggable terminals ITPluggableTerminalEventSink* m_pPTEventSink; // // we have to implement our own reference counting to work around the // problem of event sink addreffing us after we saw our last release // long m_lMyPersonalRefcount; // // this is a flag that we use to distingush between first addref and the // addref on the object whose refcount has gone down to 0. // BOOL m_bFirstAddRef; }; #endif // __MSPSTRM_H_