// // FPTrack.cpp // #include "stdafx.h" #include "FPTrack.h" #include "FPTerm.h" #include "FPFilter.h" #include ////////////////////////////////////////////////////////////////////// // // 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 , &IID_ITFileTrack, &LIBID_TAPI3Lib> CTFileTrackFPT; typedef IDispatchImpl, &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 *pAudioFormat = NULL; HRESULT hr = CComObject::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 *pVideoFormat = NULL; HRESULT hr = CComObject::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 *pAudioFormat = NULL; HRESULT hr = CComObject::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 *pVideoFormat = NULL; HRESULT hr = CComObject::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(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(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(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