Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1332 lines
27 KiB

//
// fpunit.cpp
//
#include "stdafx.h"
#include "fpunit.h"
#include "pbfilter.h"
#include "vfwmsgs.h"
//
// The unit filter name
//
WCHAR g_bstrUnitFilterName[] = L"PlaybackUnitSource";
WCHAR g_bstrUnitBridgeFilterName[] = L"PlaybackBridgeFilter";
CPlaybackUnit::CPlaybackUnit()
:m_pIGraphBuilder(NULL),
m_hGraphEventHandle(NULL),
m_pBridgeFilter(NULL),
m_pSourceFilter(NULL)
{
LOG((MSP_TRACE, "CPlaybackUnit::CPlaybackUnit[%p] - enter. ", this));
LOG((MSP_TRACE, "CPlaybackUnit::CPlaybackUnit - exit"));
}
CPlaybackUnit::~CPlaybackUnit()
{
LOG((MSP_TRACE, "CPlaybackUnit::~CPlaybackUnit[%p] - enter. ", this));
LOG((MSP_TRACE, "CPlaybackUnit::~CPlaybackUnit - exit"));
}
//
// --- Public members ---
//
/*++
Inititalize the playback unit
try to create the graph builder, initialize critical section,
rgisters for the graph events
--*/
HRESULT CPlaybackUnit::Initialize(
)
{
LOG((MSP_TRACE, "CPlaybackUnit::Initialize[%p] - enter. ", this));
//
// initialize should only be called once. it it is not, there is a bug in
// our code
//
if (NULL != m_pIGraphBuilder)
{
LOG((MSP_ERROR, "CPlaybackUnit::Initialize - already initialized"));
TM_ASSERT(FALSE);
return E_UNEXPECTED;
}
//
// attempt to initialize critical section
//
BOOL bCSInitSuccess = InitializeCriticalSectionAndSpinCount(&m_CriticalSection, 0);
if (!bCSInitSuccess)
{
LOG((MSP_ERROR,
"CPlaybackUnit::Initialize - failed to initialize critical section. LastError=%ld",
GetLastError()));
return E_OUTOFMEMORY;
}
//
// Create filter graph
//
HRESULT hr = CoCreateInstance(
CLSID_FilterGraph,
NULL,
CLSCTX_INPROC_SERVER,
IID_IGraphBuilder,
(void **) &m_pIGraphBuilder
);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CPlaybackUnit::Initialize - failed to create filter graph. Returns 0x%08x", hr));
DeleteCriticalSection(&m_CriticalSection);
return hr;
}
//
// Register for filter graph events
//
IMediaEvent *pMediaEvent = NULL;
hr = m_pIGraphBuilder->QueryInterface(IID_IMediaEvent, (void**)&pMediaEvent);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - failed to qi graph for IMediaEvent, Returns 0x%08x", hr));
// Clean-up
m_pIGraphBuilder->Release();
m_pIGraphBuilder = NULL;
DeleteCriticalSection(&m_CriticalSection);
return hr;
}
//
// Get filter graph's event
//
HANDLE hEvent = NULL;
hr = pMediaEvent->GetEventHandle((OAEVENT*)&hEvent);
//
// Clean-up
//
pMediaEvent->Release();
pMediaEvent = NULL;
if (FAILED(hr))
{
LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - failed to get graph's event. Returns 0x%08x", hr));
// Clean-up
m_pIGraphBuilder->Release();
m_pIGraphBuilder = NULL;
DeleteCriticalSection(&m_CriticalSection);
return hr;
}
//
// Register for the graph event
//
BOOL fSuccess = RegisterWaitForSingleObject(
&m_hGraphEventHandle, // pointer to the returned handle
hEvent, // the event handle to wait for.
CPlaybackUnit::HandleGraphEvent, // the callback function.
this, // the context for the callback.
INFINITE, // wait forever.
WT_EXECUTEDEFAULT |
WT_EXECUTEINWAITTHREAD // use the wait thread to call the callback.
);
if ( ! fSuccess )
{
LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - failed to register wait event", hr));
// Clean-up
m_pIGraphBuilder->Release();
m_pIGraphBuilder = NULL;
DeleteCriticalSection(&m_CriticalSection);
return hr;
}
LOG((MSP_TRACE, "CPlaybackUnit::Initialize - exit"));
return S_OK;
}
//
// SetupFromFile try to create a filter graph and
// the bridge filter with input pins based on the file
//
HRESULT CPlaybackUnit::SetupFromFile(
IN BSTR bstrFileName
)
{
LOG((MSP_TRACE, "CPlaybackUnit::SetupFromFile[%p] - enter", this));
//
// Check arguments
//
if (IsBadStringPtr(bstrFileName, -1))
{
LOG((MSP_ERROR, "CPlaybackUnit::SetupFromFile - bad file name passed in"));
TM_ASSERT(FALSE);
return E_UNEXPECTED;
}
//
// Make sure we have been initialized
//
if (NULL == m_pIGraphBuilder)
{
LOG((MSP_ERROR, "CPlaybackUnit::SetupFromFile - not yet initialized."));
TM_ASSERT(FALSE);
return E_UNEXPECTED;
}
//
// lock before accessing data members
//
CCSLock Lock(&m_CriticalSection);
//
// Make sure the graph is stopped
//
HRESULT hr = IsGraphInState( State_Stopped );
if( FAILED(hr) )
{
//
// Stop the graph
//
hr = Stop();
if( FAILED(hr) )
{
LOG((MSP_ERROR,
"CPlaybackUnit::SetupFromFile - "
"graph cannot be stop. Returns 0x%08x", hr));
return hr;
}
}
//
// Remove the existing source filter
// if we have one
//
if( m_pSourceFilter != NULL)
{
hr = RemoveSourceFilter();
if( FAILED(hr) )
{
LOG((MSP_ERROR,
"CPlaybackUnit::SetupFromFile - "
"RemoveSourceFilter failed. Returns 0x%08x", hr));
return hr;
}
}
//
// Add the source filter to the filter graph
//
hr = m_pIGraphBuilder->AddSourceFilter(
bstrFileName,
g_bstrUnitFilterName,
&m_pSourceFilter
);
if( FAILED(hr) )
{
LOG((MSP_ERROR,
"CPlaybackUnit::SetupFromFile - "
"AddSourceFilter failed. Returns 0x%08x", hr));
return hr;
}
//
// Get the source pin
//
IPin* pSourcePin = NULL;
hr = GetSourcePin( &pSourcePin );
if( FAILED(hr) )
{
// Clean-up
RemoveSourceFilter();
LOG((MSP_ERROR,
"CPlaybackUnit::SetupFromFile - "
"GetSourcePin failed. Returns 0x%08x", hr));
return hr;
}
//
// We add bridge filters to the graph
//
hr = AddBridgeFilter();
if( FAILED(hr) )
{
// Clean-up
pSourcePin->Release();
RemoveSourceFilter();
LOG((MSP_ERROR,
"CPlaybackUnit::SetupFromFile - "
"AddBridgeFilters failed. Returns 0x%08x", hr));
return hr;
}
//
// Let graph to render
//
hr = m_pIGraphBuilder->Render( pSourcePin );
if( FAILED(hr) )
{
// Clean-up
pSourcePin->Release();
RemoveSourceFilter();
LOG((MSP_ERROR,
"CPlaybackUnit::SetupFromFile - "
"AddBridgeFilters failed. Returns 0x%08x", hr));
return hr;
}
//
// Clean-up
//
pSourcePin->Release();
pSourcePin = NULL;
LOG((MSP_TRACE, "CPlaybackUnit::SetupFromFile - finished"));
return S_OK;
}
HRESULT CPlaybackUnit::GetState(OAFilterState *pGraphState)
{
LOG((MSP_TRACE, "CPlaybackUnit::GetState[%p] - enter", this));
//
// make sure we have been initialized.
//
if (NULL == m_pIGraphBuilder)
{
LOG((MSP_ERROR, "CPlaybackUnit::GetState - not yet initialized."));
TM_ASSERT(FALSE);
return E_UNEXPECTED;
}
//
// get media control interface so we change state
//
IMediaControl *pIMediaControl = NULL;
{
//
// will be accessing data members -- in a lock
//
CCSLock Lock(&m_CriticalSection);
HRESULT hr = m_pIGraphBuilder->QueryInterface(
IID_IMediaControl,
(void**)&pIMediaControl
);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CPlaybackUnit::ChangeState - failed to qi for IMediaControl. hr = %lx", hr));
return hr;
}
}
//
// try to get state outside the lock
//
OAFilterState GraphState = (OAFilterState) -1;
HRESULT hr = pIMediaControl->GetState(10, &GraphState);
pIMediaControl->Release();
pIMediaControl = NULL;
//
// did we succeed at all?
//
if (FAILED(hr))
{
LOG((MSP_ERROR,
"CPlaybackUnit::ChangeState - failed to get state. hr = %lx", hr));
return hr;
}
//
// is the state transition still in progress?
//
if (VFW_S_STATE_INTERMEDIATE == hr)
{
LOG((MSP_WARN,
"CPlaybackUnit::ChangeState - state transition in progress. "
"returNing VFW_S_STATE_INTERMEDIATE"));
//
// continue -- the state is what we are transitioning to
//
}
//
// log if we got VFW_S_CANT_CUE
//
if (VFW_S_CANT_CUE == hr)
{
LOG((MSP_WARN,
"CPlaybackUnit::GetState - fg returned VFW_S_CANT_CUE"));
//
// continue -- we still should have received a valid state
//
}
//
// log the state
//
switch (GraphState)
{
case State_Stopped:
LOG((MSP_TRACE, "CPlaybackUnit::GetState - State_Stopped"));
*pGraphState = GraphState;
break;
case State_Running:
LOG((MSP_TRACE, "CPlaybackUnit::GetState - State_Running"));
*pGraphState = GraphState;
break;
case State_Paused:
LOG((MSP_TRACE, "CPlaybackUnit::GetState- State_Paused"));
*pGraphState = GraphState;
break;
default:
LOG((MSP_TRACE, "CPlaybackUnit::GetState- unknown state %ld", GraphState));
hr = E_FAIL;
break;
}
LOG((MSP_(hr), "CPlaybackUnit::GetState - finish. hr = %lx", hr));
return hr;
}
VOID CPlaybackUnit::HandleGraphEvent(
IN VOID *pContext,
IN BOOLEAN bReason)
{
LOG((MSP_TRACE, "CPlaybackUnit::HandleGraphEvent - enter FT:[%p].", pContext));
//
// get recording unit pointer out of context
//
CPlaybackUnit *pPlaybackUnit =
static_cast<CPlaybackUnit*>(pContext);
if (IsBadReadPtr(pPlaybackUnit, sizeof(CPlaybackUnit)) )
{
LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - bad context"));
return;
}
//
// the graph was not initialized. something went wrong.
//
if (NULL == pPlaybackUnit->m_pIGraphBuilder)
{
LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - not initialized. filter graph null"));
return;
}
//
// lock the object (just in case the object pointer is bad, do inside try/catch
//
try
{
EnterCriticalSection(&(pPlaybackUnit->m_CriticalSection));
}
catch(...)
{
LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - exception accessing critical section"));
return;
}
//
// get the media event interface so we can retrieve the event
//
IMediaEvent *pMediaEvent = NULL;
HRESULT hr =
pPlaybackUnit->m_pIGraphBuilder->QueryInterface(IID_IMediaEvent,
(void**)&pMediaEvent);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - failed to qi graph for IMediaEvent"));
LeaveCriticalSection(&(pPlaybackUnit->m_CriticalSection));
return;
}
//
// while holding critical section, get the terminal on which to fire the event
//
//CFileRecordingTerminal *pRecordingterminal = pPlaybackUnit->m_pRecordingTerminal;
//pRecordingterminal->AddRef();
//
// no longer need to access data members, release critical section
//
LeaveCriticalSection(&(pPlaybackUnit->m_CriticalSection));
//
// get the actual event
//
long lEventCode = 0;
LONG_PTR lParam1 = 0;
LONG_PTR lParam2 = 0;
hr = pMediaEvent->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CPlaybackUnit::HandleGraphEvent - failed to get the event. hr = %lx", hr));
// Clean-up
pMediaEvent->FreeEventParams(lEventCode, lParam1, lParam2);
pMediaEvent->Release();
pMediaEvent = NULL;
return;
}
LOG((MSP_EVENT, "CPlaybackUnit::HandleGraphEvent - received event code:[0x%lx] param1:[%p] param2:[%p]",
lEventCode, lParam1, lParam2));
//
// ask file terminal to handle the event
//
// Clean-up
pMediaEvent->FreeEventParams(lEventCode, lParam1, lParam2);
pMediaEvent->Release();
pMediaEvent = NULL;
if (FAILED(hr))
{
LOG((MSP_ERROR,
"CPlaybackUnit::HandleGraphEvent - failed to fire event on the terminal. hr = %lx",
hr));
return;
}
}
HRESULT CPlaybackUnit::IsGraphInState(
IN OAFilterState State
)
{
LOG((MSP_TRACE, "CPlaybackUnit::IsGraphInState[%p] - enter", this));
//
// Get the graph state
//
OAFilterState DSState;
HRESULT hr = GetState(&DSState);
//
// is the state transition still in progress?
//
if (VFW_S_STATE_INTERMEDIATE == hr)
{
LOG((MSP_ERROR, "CPlaybackUnit::IsGraphInState - exit"
" graph is not yet initialized. Returns TAPI_E_WRONG_STATE"));
return TAPI_E_WRONG_STATE;
}
//
// is the return anything other than S_OK
//
if (hr != S_OK)
{
LOG((MSP_ERROR,
"CPlaybackUnit::IsGraphInState - exit "
"failed to get state of the filter graph. Returns 0x%08x", hr));
return hr;
}
if (State != DSState)
{
LOG((MSP_ERROR,
"CPlaybackUnit::IsGraphInState - exit "
"other state then we asked for. Returns TAPI_E_WRONG_STATE"));
return TAPI_E_WRONG_STATE;
}
LOG((MSP_(hr), "CPlaybackUnit::IsGraphInState - exit. Returns 0x%08x", hr));
return hr;
}
/*++
Renoves the source filter from the filter graph and
set the source filter on NULL.
--*/
HRESULT CPlaybackUnit::RemoveSourceFilter()
{
LOG((MSP_TRACE, "CPlaybackUnit::RemoveSourceFilter[%p] - enter", this));
//
// Do we have a source filter?
//
if( m_pSourceFilter == NULL )
{
LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - "
"we have a NULL source filter already. Returns S_OK"));
return S_OK;
}
//
// Get the IFilterGraph interface
//
IFilterGraph* pFilterGraph = NULL;
HRESULT hr = m_pIGraphBuilder->QueryInterface(
IID_IFilterGraph,
(void**)&pFilterGraph
);
if( FAILED(hr) )
{
LOG((MSP_ERROR,
"CPlaybackUnit::RemoveSourceFilter - "
"QI for IFilterGraph failed. Returns 0x%08x", hr));
return hr;
}
//
// Remove the source filter from the graph
//
pFilterGraph->RemoveFilter( m_pSourceFilter );
//
// Clean-up the source filter anyway
//
m_pSourceFilter->Release();
m_pSourceFilter = NULL;
// Clean-up
pFilterGraph->Release();
pFilterGraph = NULL;
LOG((MSP_(hr), "CPlaybackUnit::AddSourceFilter - exit. Returns 0x%08x", hr));
return hr;
}
/*++
Removes the bridge filter from the filter graph and
set the bridge filter on NULL.
--*/
HRESULT CPlaybackUnit::RemoveBridgeFilter(
)
{
LOG((MSP_TRACE, "CPlaybackUnit::RemoveBridgeFilter[%p] - enter", this));
//
// Do we have a bridge filter?
//
if( m_pBridgeFilter == NULL )
{
LOG((MSP_TRACE, "CPlaybackUnit::RemoveBridgeFilter - "
"we have a NULL bridge filter already. Returns S_OK"));
return S_OK;
}
//
// Get the IFilterGraph interface
//
IFilterGraph* pFilterGraph = NULL;
HRESULT hr = m_pIGraphBuilder->QueryInterface(
IID_IFilterGraph,
(void**)&pFilterGraph
);
if( FAILED(hr) )
{
LOG((MSP_ERROR,
"CPlaybackUnit::RemoveBridgeFilter - "
"QI for IFilterGraph failed. Returns 0x%08x", hr));
return hr;
}
//
// Remove the bridge filter from the graph
//
pFilterGraph->RemoveFilter( m_pBridgeFilter );
//
// Clean-up the bridge filter anyway
//
m_pBridgeFilter = NULL;
// Clean-up
pFilterGraph->Release();
pFilterGraph = NULL;
LOG((MSP_(hr), "CPlaybackUnit::RemoveBridgeFilter - exit. Returns 0x%08x", hr));
return hr;
}
HRESULT CPlaybackUnit::GetSourcePin(
OUT IPin** ppPin
)
{
LOG((MSP_TRACE, "CPlaybackUnit::GetSourcePin[%p] - enter", this));
TM_ASSERT( m_pSourceFilter );
//
// Reset the value
//
*ppPin = NULL;
//
// Get the in enumeration
//
IEnumPins* pEnumPins = NULL;
HRESULT hr = m_pSourceFilter->EnumPins( &pEnumPins );
if( FAILED(hr) )
{
LOG((MSP_ERROR,
"CPlaybackUnit::GetSourcePin - exit "
"EnumPins failed. Returns 0x%08x", hr));
return hr;
}
//
// Get the first pin
//
IPin* pPin = NULL;
ULONG uFetched = 0;
hr = pEnumPins->Next(1, &pPin, &uFetched );
//
// Release the enumeration
//
pEnumPins->Release();
pEnumPins = NULL;
if( hr != S_OK )
{
LOG((MSP_ERROR,
"CPlaybackUnit::GetSourcePin - exit "
"we don't have a pin. Returns E_FAIL"));
return E_FAIL;
}
//
// Return the pin
//
*ppPin = pPin;
LOG((MSP_TRACE, "CPlaybackUnit::GetSourcePin - exit S_OK"));
return S_OK;
}
HRESULT CPlaybackUnit::AddBridgeFilter(
)
{
LOG((MSP_TRACE, "CPlaybackUnit::AddBridgeFilter[%p] - enter", this));
if( m_pBridgeFilter )
{
LOG((MSP_TRACE, "CPlaybackUnit::AddBridgeFilter - "
"we already have a bridge filter. Return S_OK"));
return S_OK;
}
//
// Create the new bridge filter
//
m_pBridgeFilter = new CPBFilter();
if( m_pBridgeFilter == NULL)
{
LOG((MSP_ERROR,
"CPlaybackUnit::AddBridgeFilter - exit "
"new allocation for CPBFilter failed. Returns E_OUTOFMEMORY"));
return E_OUTOFMEMORY;
}
//
// Initialize the bridge filter
//
HRESULT hr = m_pBridgeFilter->Initialize( this );
if( FAILED(hr) )
{
// Clean-up
delete m_pBridgeFilter;
m_pBridgeFilter = NULL;
LOG((MSP_ERROR,
"CPlaybackUnit::AddBridgeFilter - exit "
"initialize failed. Returns 0x%08x", hr));
return hr;
}
//
// Add this bridge filter to the graph
//
hr = m_pIGraphBuilder->AddFilter(
m_pBridgeFilter,
g_bstrUnitBridgeFilterName
);
if( FAILED(hr) )
{
// Clean-up
delete m_pBridgeFilter;
m_pBridgeFilter = NULL;
LOG((MSP_ERROR,
"CPlaybackUnit::AddBridgeFilter - exit "
"Add filter failed. Returns 0x%08x", hr));
return hr;
}
LOG((MSP_(hr), "CPlaybackUnit::AddBridgeFilter - exit. Returns 0x%08x", hr));
return hr;
}
//
// retrieve the media supported by the filter
//
HRESULT CPlaybackUnit::get_MediaTypes(
OUT long* pMediaTypes
)
{
LOG((MSP_TRACE, "CPlaybackUnit::get_MediaTypes[%p] - enter", this));
TM_ASSERT( pMediaTypes != NULL );
TM_ASSERT( m_pBridgeFilter != NULL );
HRESULT hr = E_FAIL;
//
// lock before accessing data members
//
CCSLock Lock(&m_CriticalSection);
//
// Get the media types from the filter
//
hr = m_pBridgeFilter->get_MediaTypes( pMediaTypes );
if( FAILED(hr) )
{
LOG((MSP_ERROR,
"CPlaybackUnit::get_MediaTypes - exit "
"get_MediaTypes failed. Returns 0x%08x", hr));
return hr;
}
LOG((MSP_(hr), "CPlaybackUnit::get_MediaTypes - exit. Returns S_OK"));
return S_OK;
}
HRESULT CPlaybackUnit::GetMediaPin(
IN long nMediaType,
IN int nIndex,
OUT CPBPin** ppPin
)
{
LOG((MSP_TRACE, "CPlaybackUnit::GetMediaPin[%p] - enter", this));
TM_ASSERT( ppPin != NULL );
TM_ASSERT( m_pBridgeFilter != NULL );
HRESULT hr = E_FAIL;
*ppPin = NULL;
//
// lock before accessing data members
//
CCSLock Lock(&m_CriticalSection);
//
// Get the media types from the filter
//
int nPins = m_pBridgeFilter->GetPinCount();
int nMediaPin = 0;
for(int nPin=0; nPin < nPins; nPin++)
{
CPBPin* pPin = static_cast<CPBPin*>(m_pBridgeFilter->GetPin(nPin));
if( pPin )
{
long mt = 0;
pPin->get_MediaType( &mt );
if( (mt == nMediaType) && (nIndex == nMediaPin) )
{
*ppPin = pPin;
hr = S_OK;
break;
}
if( mt == nMediaType )
{
nMediaPin++;
}
}
}
LOG((MSP_(hr), "CPlaybackUnit::GetMediaPin - exit. Returns 0x%08x", hr));
return hr;
}
///////////////////////////////////////////////////////////////////////////////
HRESULT CPlaybackUnit::ChangeState(OAFilterState DesiredState)
{
LOG((MSP_TRACE, "CPlaybackUnit::ChangeState[%p] - enter", this));
//
// make sure we have been initialized
//
if (NULL == m_pIGraphBuilder)
{
LOG((MSP_ERROR, "CPlaybackUnit::ChangeState - not yet initialized."));
TM_ASSERT(FALSE);
return E_UNEXPECTED;
}
//
// check the current state first
//
OAFilterState GraphState;
HRESULT hr = GetState(&GraphState);
//
// is the state transition still in progress?
//
if (VFW_S_STATE_INTERMEDIATE == hr)
{
LOG((MSP_WARN, "CPlaybackUnit::ChangeState - state transition in progress. returing TAPI_E_WRONG_STATE"));
return TAPI_E_WRONG_STATE;
}
//
// is the return anything other than S_OK
//
if (hr != S_OK)
{
LOG((MSP_ERROR,
"CPlaybackUnit::ChangeState - failed to get state of the filter graph. hr = %lx",
hr));
return hr;
}
TM_ASSERT(hr == S_OK);
//
// nothing to do if we are already in that state
//
if (DesiredState == GraphState)
{
LOG((MSP_TRACE,
"CPlaybackUnit::ChangeState - graph is already in state %ld. nothing to do.", DesiredState));
return S_OK;
}
//
// get media control interface so we change state
//
IMediaControl *pIMediaControl = NULL;
{
//
// will be accessing data members -- in a lock
//
CCSLock Lock(&m_CriticalSection);
hr = m_pIGraphBuilder->QueryInterface(IID_IMediaControl, (void**)&pIMediaControl);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CPlaybackUnit::ChangeState - failed to qi for IMediaControl. hr = %lx", hr));
return hr;
}
}
//
// try to make state transition
//
switch (DesiredState)
{
case State_Stopped:
LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - stopping"));
hr = pIMediaControl->Stop();
break;
case State_Running:
LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - starting"));
hr = pIMediaControl->Run();
break;
case State_Paused:
LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - pausing"));
hr = pIMediaControl->Pause();
break;
default:
LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - unknown state %ld", DesiredState));
hr = E_INVALIDARG;
break;
}
pIMediaControl->Release();
pIMediaControl = NULL;
if (FAILED(hr))
{
LOG((MSP_ERROR, "CPlaybackUnit::ChangeState - state change failed. hr = %lx", hr));
return hr;
}
LOG((MSP_TRACE, "CPlaybackUnit::ChangeState - finish"));
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
HRESULT CPlaybackUnit::Start()
{
LOG((MSP_TRACE, "CPlaybackUnit::Start[%p] - enter", this));
HRESULT hr = ChangeState(State_Running);
LOG((MSP_(hr), "CPlaybackUnit::Start - finish. hr = %lx", hr));
return hr;
}
HRESULT CPlaybackUnit::Pause()
{
LOG((MSP_TRACE, "CPlaybackUnit::Pause[%p] - enter", this));
HRESULT hr = ChangeState(State_Paused);
LOG((MSP_(hr), "CPlaybackUnit::Pause - finish. hr = %lx", hr));
return hr;
}
HRESULT CPlaybackUnit::Stop()
{
LOG((MSP_TRACE, "CPlaybackUnit::Stop[%p] - enter", this));
HRESULT hr = ChangeState(State_Stopped);
LOG((MSP_(hr), "CPlaybackUnit::Stop - finish. hr = %lx", hr));
return hr;
}
HRESULT CPlaybackUnit::Shutdown()
{
//
// if we don't have filter graph, we have not passed initialization
//
if (NULL == m_pIGraphBuilder)
{
LOG((MSP_TRACE, "CPlaybackUnit::Shutdown - not yet initialized. nothing to shut down"));
return S_OK;
}
//
// first of all, make sure the graph is stopped
//
HRESULT hr = Stop();
if (FAILED(hr))
{
LOG((MSP_ERROR, "CPlaybackUnit::Shutdown - exit "
"failed to stop filter graph, hr = 0x%08x", hr));
return hr;
}
//
// unregister wait event
//
BOOL bUnregisterResult = ::UnregisterWaitEx(m_hGraphEventHandle, (HANDLE)-1);
m_hGraphEventHandle = NULL;
if (!bUnregisterResult)
{
LOG((MSP_ERROR, "CPlaybackUnit::Shutdown - failed to unregisted even. continuing anyway"));
}
//
// Remove the bridge filter
//
hr = RemoveBridgeFilter();
if( FAILED(hr) )
{
LOG((MSP_ERROR, "CPlaybackUnit::Shutdown - exit "
"RemoveBridgeFilter failed, hr = 0x%08x", hr));
return hr;
}
//
// Remove the source filter
//
hr = RemoveSourceFilter();
if( FAILED(hr) )
{
LOG((MSP_ERROR, "CPlaybackUnit::Shutdown - exit "
"RemoveSourceFilter failed, hr = 0x%08x", hr));
return hr;
}
//
// release filter graph
//
if( m_pIGraphBuilder != NULL )
{
m_pIGraphBuilder->Release();
m_pIGraphBuilder = NULL;
}
//
// no need to keep critical section around any longer -- no one should be
// using this object anymore
//
DeleteCriticalSection(&m_CriticalSection);
LOG((MSP_TRACE, "CPlaybackUnit::Shutdown - finished"));
return S_OK;
}
// eof