Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1657 lines
37 KiB

//
// FPTrack.cpp
//
#include "stdafx.h"
#include "FPTrack.h"
#include "FPTerm.h"
#include "FPFilter.h"
#include <formats.h>
//////////////////////////////////////////////////////////////////////
//
// Constructor / Destructor - Methods implementation
//
//////////////////////////////////////////////////////////////////////
CFPTrack::CFPTrack() :
m_dwMediaType(TAPIMEDIATYPE_AUDIO),
m_pFPFilter(NULL),
m_pEventSink(NULL),
m_pParentTerminal(NULL),
m_TrackState(TMS_IDLE),
m_pMediaType(NULL),
m_pSource(NULL)
{
LOG((MSP_TRACE, "CFPTrack::CFPTrack - enter"));
m_pIFilter = NULL;
m_szName[0]= (TCHAR)0;
//
// Allocator properties
//
m_AllocProp.cbAlign = -1; // no alignment
m_AllocProp.cbPrefix = -1; // no prefix
m_AllocProp.cbBuffer = 480; // each buffer is 320 bytes = 20 ms worth of data
m_AllocProp.cBuffers = 33; // read 33 buffers
LOG((MSP_TRACE, "CFPTrack::CFPTrack - exit"));
}
CFPTrack::~CFPTrack()
{
LOG((MSP_TRACE, "CFPTrack::~CFPTrack - enter"));
// Clean-up the event sink
if( NULL != m_pEventSink )
{
m_pEventSink->Release();
m_pEventSink = NULL;
}
// Clean-up parent multitrack terminal
if( NULL != m_pParentTerminal )
{
m_pParentTerminal = NULL;
}
//
// tell the filter that we are going away
//
if ( NULL != m_pFPFilter )
{
m_pFPFilter->Orphan();
}
// Clean-up the media type
if( m_pMediaType )
{
DeleteMediaType ( m_pMediaType );
m_pMediaType = NULL;
}
// Clean-up the source stream
if( m_pSource )
{
m_pSource->Release();
m_pSource = NULL;
}
// We don't need to delete m_pFPFilter because
// m_pIFilter take care of it
LOG((MSP_TRACE, "CFPTrack::~CFPTrack - exit"));
}
//////////////////////////////////////////////////////////////////////////////
//
// IDispatch implementation
//
typedef IDispatchImpl<ITFileTrackVtblFPT<CFPTrack> , &IID_ITFileTrack, &LIBID_TAPI3Lib> CTFileTrackFPT;
typedef IDispatchImpl<ITTerminalVtblBase<CBaseTerminal>, &IID_ITTerminal, &LIBID_TAPI3Lib> CTTerminalFPT;
/////////////////////////////////////////////////////////////////////////
//
// CFPTrack::GetIDsOfNames
//
//
STDMETHODIMP CFPTrack::GetIDsOfNames(REFIID riid,
LPOLESTR* rgszNames,
UINT cNames,
LCID lcid,
DISPID* rgdispid
)
{
LOG((MSP_TRACE, "CFPTrack::GetIDsOfNames[%p] - enter. Name [%S]", this, *rgszNames));
HRESULT hr = DISP_E_UNKNOWNNAME;
//
// See if the requsted method belongs to the default interface
//
hr = CTTerminalFPT::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
if (SUCCEEDED(hr))
{
LOG((MSP_TRACE, "CFPTrack::GetIDsOfNames - found %S on ITTerminal", *rgszNames));
rgdispid[0] |= 0;
return hr;
}
//
// If not, then try the ITFileTrack interface
//
hr = CTFileTrackFPT::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid);
if (SUCCEEDED(hr))
{
LOG((MSP_TRACE, "CFPTrack::GetIDsOfNames - found %S on ITFileTrack", *rgszNames));
rgdispid[0] |= IDISPFILETRACK;
return hr;
}
LOG((MSP_TRACE, "CFPTrack::GetIDsOfNames - finish. didn't find %S on our iterfaces", *rgszNames));
return hr;
}
/////////////////////////////////////////////////////////////////////////
//
// CFPTrack::Invoke
//
//
STDMETHODIMP CFPTrack::Invoke(DISPID dispidMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS* pdispparams,
VARIANT* pvarResult,
EXCEPINFO* pexcepinfo,
UINT* puArgErr
)
{
LOG((MSP_TRACE, "CFPTrack::Invoke[%p] - enter. dispidMember %lx", this, dispidMember));
HRESULT hr = DISP_E_MEMBERNOTFOUND;
DWORD dwInterface = (dispidMember & INTERFACEMASK);
//
// Call invoke for the required interface
//
switch (dwInterface)
{
case 0:
{
hr = CTTerminalFPT::Invoke(dispidMember,
riid,
lcid,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr
);
LOG((MSP_TRACE, "CFPTrack::Invoke - ITTerminal"));
break;
}
case IDISPFILETRACK:
{
hr = CTFileTrackFPT::Invoke(dispidMember,
riid,
lcid,
wFlags,
pdispparams,
pvarResult,
pexcepinfo,
puArgErr
);
LOG((MSP_TRACE, "CFPTrack::Invoke - ITFileTrack"));
break;
}
} // end switch (dwInterface)
LOG((MSP_TRACE, "CFPTrack::Invoke - finish. hr = %lx", hr));
return hr;
}
//////////////////////////////////////////////////////////////////////
//
// CBaseTerminal - Methods implementation
//
//////////////////////////////////////////////////////////////////////
HRESULT CFPTrack::AddFiltersToGraph()
{
LOG((MSP_TRACE, "CFPTrack::AddFiltersToGraph - enter"));
//
// Validates m_pGraph
//
if ( m_pGraph == NULL)
{
LOG((MSP_ERROR, "CFPTrack::AddFiltersToGraph - "
"we have no graph - returning E_UNEXPECTED"));
return E_UNEXPECTED;
}
//
// Validates m_pIFilter
//
if ( m_pIFilter == NULL)
{
LOG((MSP_ERROR, "CFPTrack::AddFiltersToGraph - "
"we have no filter - returning E_UNEXPECTED"));
return E_UNEXPECTED;
}
//
// AddFilter returns VFW_S_DUPLICATE_NAME if name is duplicate; still succeeds
//
HRESULT hr = m_pGraph->AddFilter(m_pIFilter, m_szName);
if ( FAILED(hr) )
{
LOG((MSP_ERROR, "CFPTrack::AddFiltersToGraph() - "
"Can't add filter. %08x", hr));
return hr;
}
LOG((MSP_TRACE, "CFPTrack::AddFiltersToGraph - exit S_OK"));
return S_OK;
}
//////////////////////////////////////////////////////////////////////
//
// ITPluggableTerminalInitialization - Methods implementation
//
//////////////////////////////////////////////////////////////////////
HRESULT CFPTrack::InitializeDynamic(
IN IID iidTerminalClass,
IN DWORD dwMediaType,
IN TERMINAL_DIRECTION Direction,
IN MSP_HANDLE htAddress
)
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::InitializeDynamic - enter"));
//
// Validate direction
//
if( Direction != TD_CAPTURE )
{
LOG((MSP_ERROR, "CFPTrack::InitializeDynamic - "
"invalid direction - returning E_INVALIDARG"));
return E_INVALIDARG;
}
//
// Call the base class method
//
HRESULT hr;
hr = CBaseTerminal::Initialize(iidTerminalClass,
dwMediaType,
Direction,
htAddress);
if ( FAILED(hr) )
{
LOG((MSP_ERROR, "CFPTrack::InitializeDynamic - "
"base class method failed - returning 0x%08x", hr));
return hr;
}
//
// Set the terminal info: name and type
//
hr = SetTerminalInfo();
if( FAILED(hr) )
{
LOG((MSP_ERROR, "CFPTrack::InitializeDynamic - "
"SetTerminalInfo failed - returning 0x%08x", hr));
return hr;
}
//
// Create the filter
//
hr = CreateFilter();
if( FAILED(hr) )
{
LOG((MSP_ERROR, "CFPTrack::InitializeDynamic - "
"CreateFilter failed - returning 0x%08x", hr));
return hr;
}
//
// Get the pin sets m_pIPin
//
hr = FindPin();
if( FAILED(hr) )
{
LOG((MSP_ERROR, "CFPTrack::InitializeDynamic - "
"FindPin failed - returning 0x%08x", hr));
return hr;
}
LOG((MSP_TRACE, "CFPTrack::InitializeDynamic - exit S_OK"));
return S_OK;
}
//////////////////////////////////////////////////////////////////////
//
// ITFileTrack - Methods implementation
//
//////////////////////////////////////////////////////////////////////
HRESULT CFPTrack::get_Format(OUT AM_MEDIA_TYPE **ppmt)
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::get_Format - enter [%p]", this));
//
// Validate argument
//
if( IsBadWritePtr( ppmt, sizeof( AM_MEDIA_TYPE*)) )
{
LOG((MSP_ERROR, "CFPTrack::InitializeDynamic - "
"invalid AM_MEDIA_TYPE pointer - returning E_POINTER"));
return E_POINTER;
}
//
// Have we a unit pin?
//
if( NULL == m_pMediaType )
{
LOG((MSP_ERROR, "CFPTrack::InitializeDynamic - "
"no media type - returning E_UNEXPECTED"));
return E_UNEXPECTED;
}
//
// Get the media type from stream
//
HRESULT hr = S_OK;
*ppmt = CreateMediaType( m_pMediaType );
if( *ppmt == NULL )
{
hr = E_OUTOFMEMORY;
}
LOG((MSP_TRACE, "CFPTrack::get_Format - exit 0x%08x", hr));
return hr;
}
HRESULT CFPTrack::put_Format(IN const AM_MEDIA_TYPE *pmt)
{
LOG((MSP_TRACE, "CFPTrack::get_Format - enter [%p]", this));
LOG((MSP_TRACE, "CFPTrack::get_Format - exit E_FAIL"));
return E_FAIL;
}
HRESULT CFPTrack::get_ControllingTerminal(
OUT ITTerminal **ppControllingTerminal
)
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::get_ControllingTerminal - enter [%p]", this));
//
// Validates argument
//
if( IsBadWritePtr( ppControllingTerminal, sizeof(ITTerminal*)))
{
LOG((MSP_ERROR, "CFPTrack::get_ControllingTerminal - "
"bad ITTerminal* pointer - returning E_POINTER"));
return E_POINTER;
}
//
// reset value anyway
//
*ppControllingTerminal = NULL;
//
// Validate parent
//
if( NULL == m_pParentTerminal )
{
LOG((MSP_ERROR, "CFPTrack::get_ControllingTerminal - "
"no parent - returning E_UNEXPECTED"));
return E_UNEXPECTED;
}
//
// Set value
//
*ppControllingTerminal = m_pParentTerminal;
m_pParentTerminal->AddRef();
LOG((MSP_TRACE, "CFPTrack::get_ControllingTerminal - exit S_OK"));
return S_OK;
}
HRESULT CFPTrack::get_AudioFormatForScripting(
OUT ITScriptableAudioFormat** ppAudioFormat
)
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::get_AudioFormatForScripting - enter"));
//
// Validates argument
//
if( IsBadWritePtr( ppAudioFormat, sizeof( ITScriptableAudioFormat*)) )
{
LOG((MSP_ERROR, "CFPTrack::get_AudioFormatForScripting - "
"bad ITScriptableAudioFormat* pointer - returning E_POINTER"));
return E_POINTER;
}
//
// Mediatype audio?
//
if( TAPIMEDIATYPE_AUDIO != m_dwMediaType)
{
LOG((MSP_ERROR, "CFPTrack::get_AudioFormatForScripting - "
"invalid media type - returning TAPI_E_INVALIDMEDIATYPE"));
return TAPI_E_INVALIDMEDIATYPE;
}
//
// Unit pin valid
//
if( NULL == m_pMediaType )
{
LOG((MSP_ERROR, "CFPTrack::get_AudioFormatForScripting - "
"m_pMediaType is NULL - returning E_UNEXPECTED"));
return E_UNEXPECTED;
}
//
// Create the object
//
CComObject<CTAudioFormat> *pAudioFormat = NULL;
HRESULT hr = CComObject<CTAudioFormat>::CreateInstance(&pAudioFormat);
if( FAILED(hr) )
{
LOG((MSP_ERROR, "CFPTrack::get_AudioFormatForScripting - "
"CreateInstance failed - returning 0x%08x", hr));
return hr;
}
//
// Get the interface
//
hr = pAudioFormat->QueryInterface(
IID_ITScriptableAudioFormat,
(void**)ppAudioFormat
);
if( FAILED(hr) )
{
delete pAudioFormat;
LOG((MSP_ERROR, "CFPTrack::get_AudioFormatForScripting - "
"QueryInterface failed - returning 0x%08x", hr));
return hr;
}
// Format type
if( m_pMediaType->formattype != FORMAT_WaveFormatEx)
{
(*ppAudioFormat)->Release();
*ppAudioFormat = NULL;
LOG((MSP_ERROR, "CFPTrack::get_AudioFormatForScripting - "
"formattype is not WAVEFORMATEX - Returning TAPI_E_INVALIDMEDIATYPE"));
return TAPI_E_INVALIDMEDIATYPE;
}
//
// Get WAVEFORMATEX
//
pAudioFormat->Initialize(
(WAVEFORMATEX*)(m_pMediaType->pbFormat));
LOG((MSP_TRACE, "CFPTrack::get_AudioFormatForScripting - exit S_OK"));
return S_OK;
}
HRESULT CFPTrack::put_AudioFormatForScripting(
IN ITScriptableAudioFormat* pAudioFormat
)
{
LOG((MSP_TRACE, "CFPTrack::put_AudioFormatForScripting - enter"));
LOG((MSP_TRACE, "CFPTrack::put_AudioFormatForScripting - exit E_FAIL"));
return E_FAIL;
}
/*
HRESULT CFPTrack::get_VideoFormatForScripting(
OUT ITScriptableVideoFormat** ppVideoFormat
)
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::get_VideoFormatForScripting - enter"));
//
// Validates argument
//
if( IsBadWritePtr( ppVideoFormat, sizeof( ITScriptableVideoFormat*)) )
{
LOG((MSP_ERROR, "CFPTrack::get_VideoFormatForScripting - "
"bad ITScriptableVideoFormat* pointer - returning E_POINTER"));
return E_POINTER;
}
//
// Mediatype video?
//
if( TAPIMEDIATYPE_VIDEO != m_dwMediaType)
{
LOG((MSP_ERROR, "CFPTrack::get_VideoFormatForScripting - "
"invalid media type - returning TAPI_E_INVALIDMEDIATYPE"));
return TAPI_E_INVALIDMEDIATYPE;
}
//
// Pin valid
//
if( NULL == m_pMediaType )
{
LOG((MSP_ERROR, "CFPTrack::get_VideoFormatForScripting - "
"m_pMediaType is NULL - returning E_UNEXPECTED"));
return E_UNEXPECTED;
}
//
// Create the object
//
CComObject<CTVideoFormat> *pVideoFormat = NULL;
HRESULT hr = CComObject<CTVideoFormat>::CreateInstance(&pVideoFormat);
if( FAILED(hr) )
{
LOG((MSP_ERROR, "CFPTrack::get_VideoFormatForScripting - "
"CreateInstance failed - returning 0x%08x", hr));
return hr;
}
//
// Get the interface
//
hr = pVideoFormat->QueryInterface(
IID_ITScriptableVideoFormat,
(void**)ppVideoFormat
);
if( FAILED(hr) )
{
delete pVideoFormat;
LOG((MSP_ERROR, "CFPTrack::get_VideoFormatForScripting - "
"QueryInterface failed - returning 0x%08x", hr));
return hr;
}
//
// Get video format
//
if( m_pMediaType->formattype != FORMAT_VideoInfo)
{
(*ppVideoFormat)->Release();
*ppVideoFormat = NULL;
LOG((MSP_ERROR, "CFPTrack::get_VideoFormatForScripting - "
"formattype is not VIDEOINFOHEADER - Returning TAPI_E_INVALIDMEDIATYPE"));
return TAPI_E_INVALIDMEDIATYPE;
}
//
// Get VIDEOINFOHEADER
//
pVideoFormat->Initialize(
(VIDEOINFOHEADER*)(m_pMediaType->pbFormat));
LOG((MSP_TRACE, "CFPTrack::get_VideoFormatForScripting - exit S_OK"));
return S_OK;
}
HRESULT CFPTrack::put_VideoFormatForScripting(
IN ITScriptableVideoFormat* pVideoFormat
)
{
LOG((MSP_TRACE, "CFPTrack::put_VideoFormatForScripting - enter"));
LOG((MSP_TRACE, "CFPTrack::put_VideoFormatForScripting - exit E_FAIL"));
return E_FAIL;
}
*/
HRESULT CFPTrack::get_EmptyAudioFormatForScripting(
OUT ITScriptableAudioFormat** ppAudioFormat
)
{
LOG((MSP_TRACE, "CFPTrack::get_EmptyAudioFormatForScripting - enter"));
//
// Validate argument
//
if( IsBadReadPtr( ppAudioFormat, sizeof(ITScriptableAudioFormat*)) )
{
LOG((MSP_ERROR, "CFPTrack::get_EmptyAudioFormatForScripting - "
"bad ITScriptableAudioFormat* pointer - returning E_POINTER"));
return E_POINTER;
}
//
// Create the object
//
CComObject<CTAudioFormat> *pAudioFormat = NULL;
HRESULT hr = CComObject<CTAudioFormat>::CreateInstance(&pAudioFormat);
if( FAILED(hr) )
{
LOG((MSP_ERROR, "CFPTrack::get_EmptyAudioFormatForScripting - "
"CreateInstance failed - returning 0x%08x", hr));
return hr;
}
//
// Get the interface
//
hr = pAudioFormat->QueryInterface(
IID_ITScriptableAudioFormat,
(void**)ppAudioFormat
);
if( FAILED(hr) )
{
delete pAudioFormat;
LOG((MSP_ERROR, "CFPTrack::get_EmptyAudioFormatForScripting - "
"QueryInterface failed - returning 0x%08x", hr));
return hr;
}
LOG((MSP_TRACE, "CFPTrack::get_EmptyAudioFormatForScripting - exit S_OK"));
return S_OK;
}
/*
HRESULT CFPTrack::get_EmptyVideoFormatForScripting(
OUT ITScriptableVideoFormat** ppVideoFormat
)
{
LOG((MSP_TRACE, "CFPTrack::get_EmptyVideoFormatForScripting - enter"));
//
// Validate argument
//
if( IsBadReadPtr( ppVideoFormat, sizeof(ITScriptableVideoFormat*)) )
{
LOG((MSP_ERROR, "CFPTrack::get_EmptyVideoFormatForScripting - "
"bad ITScriptableVideoFormat* pointer - returning E_POINTER"));
return E_POINTER;
}
//
// Create the object
//
CComObject<CTVideoFormat> *pVideoFormat = NULL;
HRESULT hr = CComObject<CTVideoFormat>::CreateInstance(&pVideoFormat);
if( FAILED(hr) )
{
LOG((MSP_ERROR, "CFPTrack::get_EmptyVideoFormatForScripting - "
"CreateInstance failed - returning 0x%08x", hr));
return hr;
}
//
// Get the interface
//
hr = pVideoFormat->QueryInterface(
IID_ITScriptableVideoFormat,
(void**)ppVideoFormat
);
if( FAILED(hr) )
{
delete pVideoFormat;
LOG((MSP_ERROR, "CFPTrack::get_EmptyVideoFormatForScripting - "
"QueryInterface failed - returning 0x%08x", hr));
return hr;
}
LOG((MSP_TRACE, "CFPTrack::get_EmptyVideoFormatForScripting - exit S_OK"));
return S_OK;
}
*/
//////////////////////////////////////////////////////////////////////
//
// ITPluggableTerminalEventSinkRegistration - Methods implementation
//
//////////////////////////////////////////////////////////////////////
HRESULT CFPTrack::RegisterSink(
IN ITPluggableTerminalEventSink *pSink
)
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::RegisterSink - enter [%p]", this));
//
// Validates argument
//
if( IsBadReadPtr( pSink, sizeof(ITPluggableTerminalEventSink)) )
{
LOG((MSP_ERROR, "CFPTrack::RegisterSink - exit "
"ITPluggableTerminalEventSink invalid pointer. Returns E_POINTER"));
return E_POINTER;
}
//
// Release the old event sink
//
if( m_pEventSink )
{
m_pEventSink->Release();
m_pEventSink = NULL;
}
//
// Set the new event sink
//
m_pEventSink = pSink;
m_pEventSink->AddRef();
LOG((MSP_TRACE, "CFPTrack::RegisterSink - exit S_OK"));
return S_OK;
}
HRESULT CFPTrack::UnregisterSink()
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::UnregisterSink - enter [%p]", this));
//
// Release the old event sink
//
if( m_pEventSink )
{
m_pEventSink->Release();
m_pEventSink = NULL;
}
LOG((MSP_TRACE, "CFPTrack::UnregisterSink - exit S_OK"));
return S_OK;
}
//////////////////////////////////////////////////////////////////////
//
// ITMediaControl - Methods implementation
//
//////////////////////////////////////////////////////////////////////
HRESULT CFPTrack::Start( )
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::Start - enter [%p]", this));
//
// Validates filter pointer
//
if( IsBadReadPtr( m_pFPFilter, sizeof( CFPFilter) ))
{
LOG((MSP_ERROR, "CFPTrack::Start - "
"pointer to filter is NULL. Returns E_UNEXPECTED"));
return E_UNEXPECTED;
}
HRESULT hr = S_OK;
hr = m_pFPFilter->StreamStart();
if( SUCCEEDED(hr) )
{
m_TrackState = TMS_ACTIVE;
}
LOG((MSP_TRACE, "CFPTrack::Start - exit 0x%08", hr));
return hr;
}
HRESULT CFPTrack::Stop( )
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::Stop - enter [%p]", this));
//
// Validates filter pointer
//
if( IsBadReadPtr( m_pFPFilter, sizeof( CFPFilter) ))
{
LOG((MSP_ERROR, "CFPTrack::Stop - "
"pointer to filter is NULL. Returns E_UNEXPECTED"));
return E_UNEXPECTED;
}
HRESULT hr = S_OK;
hr = m_pFPFilter->StreamStop();
m_TrackState = TMS_IDLE;
LOG((MSP_TRACE, "CFPTrack::Stop - exit 0x%08", hr));
return hr;
}
HRESULT CFPTrack::Pause( )
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::Pause - enter [%p]", this));
//
// Validates filter pointer
//
if( IsBadReadPtr( m_pFPFilter, sizeof( CFPFilter) ))
{
LOG((MSP_ERROR, "CFPTrack::Pause - "
"pointer to filter is NULL. Returns E_UNEXPECTED"));
return E_UNEXPECTED;
}
HRESULT hr = S_OK;
hr = m_pFPFilter->StreamPause();
if( SUCCEEDED(hr) )
{
m_TrackState = TMS_PAUSED;
}
LOG((MSP_TRACE, "CFPTrack::Pause - exit 0x%08", hr));
return hr;
}
HRESULT CFPTrack::get_MediaState(
OUT TERMINAL_MEDIA_STATE *pMediaState)
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::get_MediaState[%p] - enter.", this));
//
// Validates argument
//
if( IsBadWritePtr( pMediaState, sizeof(TERMINAL_MEDIA_STATE)) )
{
LOG((MSP_ERROR, "CFPTrack::get_MediaState - exit "
"invalid TERMINAL_MEDIA_STATE. Returns E_POINTER"));
return E_POINTER;
}
//
// Return state
//
*pMediaState = m_TrackState;
LOG((MSP_TRACE, "CFPTrack::get_MediaState - exit S_OK"));
return S_OK;
}
HRESULT CFPTrack::SetParent(
IN ITTerminal* pParent,
OUT LONG *plCurrentRefcount
)
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::SetParent[%p] - enter. parent [%p]",
this, pParent));
//
// Validates argument (it is ok for parent to be NULL)
//
if( ( NULL != pParent ) && IsBadReadPtr( pParent, sizeof(ITTerminal) ) )
{
LOG((MSP_ERROR, "CFPTrack::SetParent - "
"invalid ITTerminal pointer. Returns E_POINTER"));
return E_POINTER;
}
if( IsBadWritePtr( plCurrentRefcount, sizeof(LONG)) )
{
LOG((MSP_ERROR, "CFPTrack::SetParent - "
"invalid ITTerminal pointer. Returns E_POINTER"));
return E_POINTER;
}
//
// Release the old parent
//
if( NULL != m_pParentTerminal )
{
LOG((MSP_TRACE,
"CFPTrack::SetParent - letting go of an existing parent [%p]",
m_pParentTerminal));
m_pParentTerminal = NULL;
}
//
// Set the new parent
//
if( pParent )
{
LOG((MSP_TRACE,
"CFPTrack::SetParent - keeping the new parent [%p]",
pParent));
m_pParentTerminal = pParent;
}
//
// return current reference count so the parent can update the total it is
// keeping
//
*plCurrentRefcount = m_dwRef;
LOG((MSP_TRACE, "CFPTrack::SetParent - exit S_OK"));
return S_OK;
}
//////////////////////////////////////////////////////////////////////
//
// ITFPEventSink - Methods implementation
//
//////////////////////////////////////////////////////////////////////
HRESULT CFPTrack::FireEvent(TERMINAL_MEDIA_STATE tmsState,
FT_STATE_EVENT_CAUSE ftecEventCause,
HRESULT hrErrorCode)
{
LOG((MSP_TRACE, "CFPTrack::FireEvent - enter [%p]", this));
//
// we need a sync before we can fire an event
//
CLock lock(m_Lock);
if (NULL == m_pEventSink)
{
LOG((MSP_WARN, "CFPTrack::FireEvent - no sink"));
return E_FAIL;
}
//
// initilize the structure
//
MSP_EVENT_INFO mspEventInfo;
mspEventInfo.dwSize = sizeof(MSP_EVENT_INFO);
mspEventInfo.Event = ME_FILE_TERMINAL_EVENT;
mspEventInfo.hCall = NULL;
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.TerminalMediaState = tmsState;
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.ftecEventCause = ftecEventCause;
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.hrErrorCode = hrErrorCode;
//
// keep the pointer to our ITTerminal interface in the structure
//
HRESULT hr = _InternalQueryInterface(IID_ITFileTrack,
(void**)&(mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack));
if (FAILED(hr))
{
LOG((MSP_ERROR, "CFPTrack::FireEvent - failed to get ITFileTrack interface"));
return hr;
}
//
// get a pointer to ITTerminal of the parent terminal
//
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal = NULL;
if (NULL != m_pParentTerminal)
{
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal = m_pParentTerminal;
m_pParentTerminal->AddRef();
}
else
{
//
// if we don't have the parent, fail
//
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack->Release();
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack = NULL;
LOG((MSP_ERROR, "CFPTrack::FireEvent - failed to get controlling terminal"));
return E_FAIL;
}
//
// pass event to the msp
//
hr = m_pEventSink->FireEvent(&mspEventInfo);
if (FAILED(hr))
{
//
// release all interfaces that we are holding.
// fire event failed so no one else will release then for us.
//
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack->Release();
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pFileTrack = NULL;
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal->Release();
mspEventInfo.MSP_FILE_TERMINAL_EVENT_INFO.pParentFileTerminal = NULL;
LOG((MSP_ERROR, "CFPTrack::FireEvent - FireEvent on sink failed. hr = %lx", hr));
return hr;
}
//
// event fired
//
LOG((MSP_TRACE, "CFPTrack::FireEvent - finish"));
return S_OK;
}
//////////////////////////////////////////////////////////////////////
//
// Helper methods - Methods implementation
//
//////////////////////////////////////////////////////////////////////
HRESULT CFPTrack::InitializePrivate(
IN DWORD dwMediaType,
IN AM_MEDIA_TYPE* pMediaType,
IN ITTerminal* pParent,
IN ALLOCATOR_PROPERTIES allocprop,
IN IStream* pStream
)
{
//
// Critical section
//
CLock lock(m_Lock);
LOG((MSP_TRACE, "CFPTrack::InitializePrivate - enter [%p]", this));
if( (m_dwMediaType != TAPIMEDIATYPE_AUDIO) &&
(m_dwMediaType != TAPIMEDIATYPE_VIDEO))
{
LOG((MSP_ERROR, "CFPTrack::InitializePrivate - "
"invalid media type - returns E_INVALIDARG"));
return E_INVALIDARG;
}
//
// Get the mediatype
//
m_pMediaType = CreateMediaType( pMediaType );
if( m_pMediaType == NULL)
{
LOG((MSP_TRACE,
"CFPTrack::InitializePrivate - "
" CreateMediaType failed. return E_OUTOFMEMORY" ));
return E_OUTOFMEMORY;
}
//
// Set media type
//
m_dwMediaType = dwMediaType;
//
// Set the allocator properties
//
m_AllocProp = allocprop;
//
// let go of the existing parent
//
if( m_pParentTerminal )
{
LOG((MSP_TRACE,
"CFPTrack::InitializePrivate - letting go of parent [%p]",
m_pParentTerminal));
m_pParentTerminal = NULL;
}
//
// Set the source stream
//
HRESULT hr = pStream->Clone(&m_pSource);
if( FAILED(hr) )
{
LOG((MSP_ERROR,
"CFPTrack::InitializePrivate - "
" Clone failed. return 0x%08x", hr ));
return hr;
}
//
// keep the new parent
//
m_pParentTerminal = pParent;
LOG((MSP_TRACE,
"CFPTrack::InitializePrivate - exit S_OK. new parent [%p]",
m_pParentTerminal));
return S_OK;
}
/*++
SetTerminalInfo
Sets the name of the terminal and the terminal type
Is called by InitializeDynamic
--*/
HRESULT CFPTrack::SetTerminalInfo()
{
LOG((MSP_TRACE, "CFPTrack::SetTerminalInfo - enter"));
//
// Get the name from the resource file
// if wasn't already read
//
if( m_szName[0] == (TCHAR)0)
{
//
// Read the name
//
TCHAR szName[ MAX_PATH ];
if(::LoadString(_Module.GetResourceInstance(), IDS_FPTRACK, szName, MAX_PATH))
{
lstrcpyn( m_szName, szName, MAX_PATH);
}
else
{
LOG((MSP_ERROR, "CFPTrack::SetTerminalInfo - exit "
"LoadString failed. Returns E_OUTOFMEMORY"));
return E_OUTOFMEMORY;
}
}
//
// Sets the terminal type (TT_DYNAMIC)
//
m_TerminalType = TT_DYNAMIC;
LOG((MSP_TRACE, "CFPTrack::SetTerminalInfo - exit S_OK"));
return S_OK;
}
/*++
CreateFilter
Create the internal filter
Is called by InitializeDynamic
--*/
HRESULT CFPTrack::CreateFilter()
{
LOG((MSP_TRACE, "CFPTrack::CreateFilter - enter"));
//
// Create the filter
//
CFPFilter* pFilter = new CFPFilter( m_AllocProp );
if( NULL == pFilter )
{
LOG((MSP_ERROR, "CFPTrack::CreateFilter - "
"create filter failed - returning E_OUTOFMEMORY"));
return E_OUTOFMEMORY;
}
//
// Keep this reference
//
m_pFPFilter = pFilter;
//
// Initialize filter
//
HRESULT hr = pFilter->InitializePrivate(
m_dwMediaType,
&m_Lock,
m_pMediaType,
this,
m_pSource);
if( FAILED(hr) )
{
// Clean-up
delete m_pFPFilter;
m_pFPFilter = NULL;
LOG((MSP_ERROR, "CFPTrack::CreateFilter - "
"InitializePrivate failed - returning 0x%08x", hr));
return hr;
}
//
// Get IBaseFilter interface
//
hr = pFilter->QueryInterface(
IID_IBaseFilter,
(void**)&m_pIFilter
);
if( FAILED(hr) )
{
// Clean-up
delete m_pFPFilter;
m_pFPFilter = NULL;
LOG((MSP_ERROR, "CFPTrack::CreateFilter - "
"QI for IBaseFilter failed - returning 0x%08x", hr));
return hr;
}
LOG((MSP_TRACE, "CFPTrack::CreateFilter - exit S_OK"));
return S_OK;
}
/*++
FindPin
Get the pin from the filter and set the m_pIPin member
Is called by InitializeDynamic
--*/
HRESULT CFPTrack::FindPin()
{
LOG((MSP_TRACE, "CFPTrack::FindPin - enter"));
//
// Validates the filter object (smart pointer)
//
if (m_pIFilter == NULL)
{
LOG((MSP_ERROR, "CFPTrack::FindPin - "
"filter object is NULL - returning E_POINTER"));
return E_POINTER;
}
//
// Make sure the IPin object is not initialized
//
if (m_pIPin != NULL)
{
LOG((MSP_ERROR, "CFPTrack::FindPin - "
"already got a pin - returning E_INVALIDARG"));
return E_INVALIDARG;
}
HRESULT hr;
IEnumPins* pIEnumPins;
ULONG cFetched;
//
// Get the pins collection
//
hr = m_pIFilter->EnumPins(&pIEnumPins);
if( FAILED(hr) )
{
LOG((MSP_ERROR, "CFPTrack::FindPin - "
"cannot enums - returning 0x%08x", hr));
return hr;
}
//
// Get the out pin of the FilePlayback Filter
//
hr = pIEnumPins->Next(1, &m_pIPin, &cFetched);
//
// Clean-up
//
pIEnumPins->Release();
if( FAILED(hr) )
{
LOG((MSP_ERROR,
"CFPTrack::FindPin - "
"cannot get a pin - returning 0x%08x", hr));
}
LOG((MSP_TRACE, "CFPTrack::FindPin - exit S_OK"));
return S_OK;
}
HRESULT
CFPTrack::PinSignalsStop(FT_STATE_EVENT_CAUSE why,
HRESULT hrErrorCode)
{
LOG((MSP_TRACE, "CFPTrack::PinSignalsStop[%p] - enter", this));
ITTerminal *pParentTerminal = NULL;
{
//
// get parent terminal in a lock
//
// it is safe to addref/release a parent while in a lock, since parent
// uses a special lock for addref/release, but we should not make other
// calls into the parent while holding our lock -- if we do, we may
// have a deadlock if the parent decides to addref of release us while
// holding its own lock.
//
m_Lock.Lock();
if (NULL != m_pParentTerminal)
{
pParentTerminal = m_pParentTerminal;
m_pParentTerminal->AddRef();
}
m_Lock.Unlock();
}
//
// if we have a parent -- try to notify it
//
// note: this should not be done while holding a lock on the track to
// prevent deadlocks when parent addrefs a track while holding its lock
//
if (NULL != pParentTerminal)
{
//
// tell the parent terminal that we stopped
//
CFPTerminal *pFilePlaybackTerminal = static_cast<CFPTerminal *>(pParentTerminal);
if (NULL != pFilePlaybackTerminal)
{
LOG((MSP_TRACE, "CFPTrack::PinSignalsStop - notifying parent"));
pFilePlaybackTerminal->TrackStateChange(TMS_IDLE, why, hrErrorCode);
//
// no longer need pointer to the object
//
pFilePlaybackTerminal = NULL;
}
else
{
LOG((MSP_ERROR,
"CFPTrack::PinSignalsStop - pin stopped, but the parent is not of the right type. cannot notify parent"));
TM_ASSERT(FALSE);
}
pParentTerminal->Release();
pParentTerminal = NULL;
}
else
{
LOG((MSP_WARN, "CFPTrack::PinSignalsStop - pin stopped, but there is no parent to notify"));
}
LOG((MSP_TRACE, "CFPTrack::PinSignalsStop - finish"));
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
ULONG CFPTrack::InternalAddRef()
{
LOG((MSP_TRACE, "CFPTrack::InternalAddRef[%p] - enter.", this));
CLock lock(m_Lock);
//
// attempt to notify a parent, if we have one. otherwise simply decrement
// our refcount
//
if (NULL != m_pParentTerminal)
{
LOG((MSP_TRACE, "CFPTrack::InternalAddRef - notifying the parent."));
CFPTerminal *pParentPlaybackObject = static_cast<CFPTerminal *>(m_pParentTerminal);
//
// propagate release to the parent
//
pParentPlaybackObject->ChildAddRef();
//
// if the parent has gone away, it will set my parent pointer to null, and call release on me again.
// that is ok -- i (the track) will not go away until the first call to release completes and decrements refcount to 0
//
}
ULONG ulReturnValue = InterlockedIncrement(&m_dwRef);
LOG((MSP_TRACE, "CFPTrack::InternalAddRef - finish. ulReturnValue %lu", ulReturnValue));
return ulReturnValue;
}
/////////////////////////////////////////////////////////////////////////////
ULONG CFPTrack::InternalRelease()
{
LOG((MSP_TRACE, "CFPTrack::InternalRelease[%p] - enter.", this));
CLock lock(m_Lock);
//
// attempt to notify a parent, if we have one. otherwise simply decrement
// our refcount
//
if (NULL != m_pParentTerminal)
{
LOG((MSP_TRACE, "CFPTrack::InternalRelease - notifying the parent."));
CFPTerminal *pParentTerminalObject = static_cast<CFPTerminal *>(m_pParentTerminal);
//
// propagate release to the parent
//
pParentTerminalObject->ChildRelease();
//
// if the parent has gone away, it will set my parent pointer to null, and call release on me again.
// that is ok -- i (the track) will not go away until the first call to release completes and decrements refcount to 0
//
}
//
// decrement and return new refcount
//
ULONG ulReturnValue = InterlockedDecrement(&m_dwRef);
LOG((MSP_TRACE, "CFPTrack::InternalRelease - finish. ulReturnValue %lu", ulReturnValue));
return ulReturnValue;
}
//eof