|
|
/*++
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<CComMultiThreadModel>, 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<CComMultiThreadModelNoCS>, public IDispatchImpl<ITStream, &IID_ITStream, &LIBID_TAPI3Lib> { 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 <ITTerminal *> 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_
|