2025-11-28 00:35:46 +09:00

1088 lines
27 KiB
C++

/*++
Copyright (c) 1999 - 2000 Microsoft Corporation
Module Name:
sampstrm.cpp
Abstract:
This module contains the implementation for a sample MSP stream class.
--*/
#include "stdafx.h"
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
CSampleMSPStream::CSampleMSPStream() : CMSPStream()
{
LOG((MSP_TRACE, "CSampleMSPStream::CSampleMSPStream entered."));
m_fTransportConfigured = FALSE;
m_fTerminalConnected = FALSE;
m_DesiredGraphState = State_Stopped;
m_ActualGraphState = State_Stopped;
//
// INSERT HERE: initialize other data members
//
LOG((MSP_TRACE, "CSampleMSPStream::CSampleMSPStream exited."));
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
CSampleMSPStream::~CSampleMSPStream()
{
LOG((MSP_TRACE, "CSampleMSPStream::~CSampleMSPStream entered."));
LOG((MSP_TRACE, "CSampleMSPStream::~CSampleMSPStream exited."));
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
void CSampleMSPStream::FinalRelease()
{
LOG((MSP_TRACE, "CSampleMSPStream::FinalRelease entered."));
//
// At this point we should have no terminals selected, since
// Shutdown is supposed to be called before we are destructed.
//
_ASSERTE( 0 == m_Terminals.GetSize() );
if ( m_fTransportConfigured )
{
//
// INSERT HERE: Remove our transport filters from the graph and
// release them.
//
}
//
// Call the base class method to clean up everything else.
//
CMSPStream::FinalRelease();
LOG((MSP_TRACE, "CSampleMSPStream::FinalRelease exited."));
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP CSampleMSPStream::get_Name (
OUT BSTR * ppName
)
{
LOG((MSP_TRACE, "CSampleMSPStream::get_Name - enter"));
//
// Check argument.
//
if (!ppName)
{
LOG((MSP_TRACE, "CSampleMSPStream::get_Name - "
"bad return pointer - returning E_POINTER"));
return E_POINTER;
}
//
// Decide what string to return based on which stream this is.
//
ULONG ulID;
if ( m_Direction == TD_CAPTURE )
{
ulID = IDS_CAPTURE_STREAM;
}
else
{
ulID = IDS_RENDER_STREAM;
}
//
// Get the string from the string table.
//
const int ciAllocSize = 2048;
WCHAR wszName[ciAllocSize];
int iReturn = LoadString( _Module.GetModuleInstance(),
ulID,
wszName,
ciAllocSize - 1 );
if ( iReturn == 0 )
{
_ASSERTE( FALSE );
*ppName = NULL;
LOG((MSP_ERROR, "CSampleMSPStream::get_Name - "
"LoadString failed - returning E_UNEXPECTED"));
return E_UNEXPECTED;
}
//
// Convert to a BSTR and return the BSTR.
//
*ppName = SysAllocString(wszName);
if ( *ppName == NULL )
{
LOG((MSP_ERROR, "CSampleMSPStream::get_Name - "
"SysAllocString failed - returning E_OUTOFMEMORY"));
return E_OUTOFMEMORY;
}
LOG((MSP_TRACE, "CSampleMSPStream::get_Name - exit S_OK"));
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// This implementation, typical of the simplest MSPs, limits each stream to
// having at most one terminal selected at a time.
//
STDMETHODIMP CSampleMSPStream::SelectTerminal(
IN ITTerminal * pTerminal
)
{
LOG((MSP_TRACE, "CSampleMSPStream::SelectTerminal - enter"));
//
// We are going to access the terminal list -- grab the lock
//
CLock lock(m_lock);
//
// Reject if we already have a terminal selected.
//
if ( 0 != m_Terminals.GetSize() )
{
LOG((MSP_ERROR, "CSampleMSPStream::SelectTerminal - "
"exit TAPI_E_MAXTERMINALS"));
return TAPI_E_MAXTERMINALS;
}
//
// Use base class method to add it to our list of terminals.
//
HRESULT hr = CMSPStream::SelectTerminal(pTerminal);
if ( FAILED(hr) )
{
LOG((MSP_ERROR, "CSampleMSPStream::SelectTerminal - "
"base class method failed - exit 0x%08x", hr));
return hr;
}
//
// Re-pause or re-start the stream if needed.
//
if ( m_DesiredGraphState == State_Paused )
{
hr = PauseStream();
}
else if ( m_DesiredGraphState == State_Running )
{
hr = StartStream();
}
else
{
_ASSERTE( m_DesiredGraphState == State_Stopped );
hr = S_OK;
}
if ( FAILED(hr) )
{
LOG((MSP_TRACE, "CSampleMSPStream::SelectTerminal - "
"can't regain old graph state - unselecting terminal - "
"exit 0x%08x", hr));
//
// Unselect it to undo all of the above.
//
UnselectTerminal(pTerminal);
return hr;
}
LOG((MSP_TRACE, "CSampleMSPStream::SelectTerminal - exit S_OK"));
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP CSampleMSPStream::UnselectTerminal (
IN ITTerminal * pTerminal
)
{
LOG((MSP_TRACE, "CSampleMSPStream::UnselectTerminal - enter"));
CLock lock(m_lock);
//
// Use base class method to remove terminal from our list of terminals.
//
// Note: the failure cases are messy here. In this sample implementation
// we choose to return an error code but release our reference to the
// terminal when disconnection fails. This is typically better than
// keeping our reference to the terminal, which would cause us to leak
// the terminal whenever disconnection fails.
//
HRESULT hr = CMSPStream::UnselectTerminal(pTerminal);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CSampleMSPStream::UnselectTerminal - "
"base class method failed - exit 0x%08x", hr));
return hr;
}
//
// Stop the graph and disconnect the terminal if this call had it
// connected. (We need a stopped graph to disconnect properly, and
// couldn't have started the graph if the terminal isn't connected.)
//
if ( m_fTerminalConnected )
{
//
// At this point we need to make sure the stream is stopped.
// We can't use our own StopStream method because it
// (1) changes the desired graph state to Stopped and
// (2) does nothing if no terminal has been selected (which it now
// thinks is the case)
//
_ASSERTE( m_fTransportConfigured );
//
// Stop the stream via the base class method.
//
hr = CMSPStream::StopStream();
m_ActualGraphState = State_Stopped;
if ( FAILED(hr) )
{
LOG((MSP_ERROR, "CSampleMSPStream::UnselectTerminal - "
"Stop failed - 0x%08x", hr));
// don't return hr -- we really want to continue and
// disconnect if we can!
}
//
// Get the ITTerminalControl interface.
//
ITTerminalControl * pTerminalControl;
hr = pTerminal->QueryInterface(IID_ITTerminalControl,
(void **) &pTerminalControl);
if ( FAILED(hr) )
{
LOG((MSP_ERROR, "CSampleMSPStream::UnselectTerminal - "
"QI for ITTerminalControl failed - exit 0x%08x", hr));
return hr;
}
//
// Disconnect the terminal.
//
hr = pTerminalControl->DisconnectTerminal(m_pIGraphBuilder, 0);
pTerminalControl->Release();
m_fTerminalConnected = FALSE;
if ( FAILED(hr) )
{
LOG((MSP_ERROR, "CSampleMSPStream::UnselectTerminal - "
"DisconnectTerminal failed - exit 0x%08x", hr));
return hr;
}
//
// INSERT HERE: Additional disconnection may be needed, for example
// for transport fitlers or transform filters that need to be
// used for some terminals but not for others.
//
}
LOG((MSP_TRACE, "CSampleMSPStream::UnselectTerminal - exit S_OK"));
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP CSampleMSPStream::StartStream (void)
{
LOG((MSP_TRACE, "CSampleMSPStream::StartStream - enter"));
CLock lock(m_lock);
m_DesiredGraphState = State_Running;
//
// Can't start the stream if our transport filters are not configured.
//
if ( ! m_fTransportConfigured )
{
LOG((MSP_WARN, "CSampleMSPStream::PauseStream - "
"transport not configured so nothing to do yet - exit S_OK"));
return S_OK;
}
//
// Can't start the stream if no terminal has been selected.
//
if ( 0 == m_Terminals.GetSize() )
{
LOG((MSP_WARN, "CSampleMSPStream::StartStream - "
"no Terminal so nothing to do yet - exit S_OK"));
return S_OK;
}
//
// Connect the terminal. This does nothing if this call already
// connected the terminal and fails if another call has the
// terminal connected.
//
HRESULT hr;
hr = ConnectTerminal(m_Terminals[0]);
if ( FAILED(hr) )
{
FireEvent(CALL_TERMINAL_FAIL, hr, CALL_CAUSE_CONNECT_FAIL);
FireEvent(CALL_STREAM_FAIL, hr, CALL_CAUSE_CONNECT_FAIL);
LOG((MSP_ERROR, "CSampleMSPStream::StartStream - "
"our ConnectTerminal failed - exit 0x%08x", hr));
return hr;
}
//
// Run the stream via the base class method.
//
hr = CMSPStream::StartStream();
if ( FAILED(hr) )
{
//
// Failed to run -- tell the app.
//
FireEvent(CALL_STREAM_FAIL, hr, CALL_CAUSE_UNKNOWN);
LOG((MSP_ERROR, "CSampleMSPStream::StartStream - "
"Run failed - exit 0x%08x", hr));
return hr;
}
//
// Fire event if this just made us active.
//
if ( m_ActualGraphState != State_Running )
{
m_ActualGraphState = State_Running;
HRESULT hr2 = FireEvent(CALL_STREAM_ACTIVE, hr, CALL_CAUSE_LOCAL_REQUEST);
if ( FAILED(hr2) )
{
LOG((MSP_ERROR, "CSampleMSPStream::StartStream - "
"FireEvent failed - exit 0x%08x", hr2));
return hr2;
}
}
LOG((MSP_TRACE, "CSampleMSPStream::StartStream - exit S_OK"));
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP CSampleMSPStream::PauseStream (void)
{
LOG((MSP_TRACE, "CSampleMSPStream::PauseStream - enter"));
CLock lock(m_lock);
m_DesiredGraphState = State_Paused;
//
// Can't pause the stream if our transport filters are not configured.
//
if ( ! m_fTransportConfigured )
{
LOG((MSP_WARN, "CSampleMSPStream::PauseStream - "
"transport not configured so nothing to do yet - exit S_OK"));
return S_OK;
}
//
// Can't pause the stream if no terminal has been selected.
//
if ( 0 == m_Terminals.GetSize() )
{
LOG((MSP_WARN, "CSampleMSPStream::PauseStream - "
"no Terminal so nothing to do yet - exit S_OK"));
return S_OK;
}
//
// Connect the terminal. This does nothing if this call already
// connected the terminal and fails if another call has the
// terminal connected.
//
HRESULT hr;
hr = ConnectTerminal(m_Terminals[0]);
if ( FAILED(hr) )
{
FireEvent(CALL_TERMINAL_FAIL, hr, CALL_CAUSE_CONNECT_FAIL);
FireEvent(CALL_STREAM_FAIL, hr, CALL_CAUSE_CONNECT_FAIL);
LOG((MSP_ERROR, "CSampleMSPStream::StartStream - "
"our ConnectTerminal failed - exit 0x%08x", hr));
return hr;
}
//
// Pause the stream via the base class method.
//
hr = CMSPStream::PauseStream();
if ( FAILED(hr) )
{
//
// Failed to pause -- tell the app.
//
FireEvent(CALL_STREAM_FAIL, hr, CALL_CAUSE_UNKNOWN);
LOG((MSP_ERROR, "CSampleMSPStream::PauseStream - "
"Pause failed - exit 0x%08x", hr));
return hr;
}
//
// Fire event if this just made us inactive.
//
if ( m_ActualGraphState == State_Running )
{
HRESULT hr2 = FireEvent(CALL_STREAM_INACTIVE, hr, CALL_CAUSE_LOCAL_REQUEST);
if ( FAILED(hr2) )
{
m_ActualGraphState = State_Paused;
LOG((MSP_ERROR, "CSampleMSPStream::PauseStream - "
"FireEvent failed - exit 0x%08x", hr2));
return hr2;
}
}
m_ActualGraphState = State_Paused;
LOG((MSP_TRACE, "CSampleMSPStream::PauseStream - exit S_OK"));
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP CSampleMSPStream::StopStream (void)
{
LOG((MSP_TRACE, "CSampleMSPStream::StopStream - enter"));
CLock lock(m_lock);
m_DesiredGraphState = State_Stopped;
//
// Nothing to do if our transport is not configured.
//
if ( ! m_fTransportConfigured )
{
LOG((MSP_WARN, "CSampleMSPStream::StopStream - "
"transport not configured - exit S_OK"));
return S_OK;
}
//
// Nothing to do if no terminal has been selected.
//
if ( 0 == m_Terminals.GetSize() )
{
LOG((MSP_WARN, "CSampleMSPStream::StopStream - "
"no Terminal - exit S_OK"));
return S_OK;
}
//
// Stop the stream via the base class method.
//
HRESULT hr;
hr = CMSPStream::StopStream();
if ( FAILED(hr) )
{
//
// Failed to stop -- tell the app.
//
FireEvent(CALL_STREAM_FAIL, hr, CALL_CAUSE_UNKNOWN);
m_DesiredGraphState = m_ActualGraphState;
LOG((MSP_ERROR, "CSampleMSPStream::StopStream - "
"Stop failed - exit 0x%08x", hr));
return hr;
}
//
// Fire event if this just made us inactive.
//
if ( m_ActualGraphState == State_Running )
{
HRESULT hr2 = FireEvent(CALL_STREAM_INACTIVE, hr, CALL_CAUSE_LOCAL_REQUEST);
if ( FAILED(hr2) )
{
m_ActualGraphState = State_Stopped;
LOG((MSP_ERROR, "CSampleMSPStream::StopStream - "
"FireEvent failed - exit 0x%08x", hr2));
return hr2;
}
}
m_ActualGraphState = State_Stopped;
LOG((MSP_TRACE, "CSampleMSPStream::StopStream - exit S_OK"));
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// A real MSP would have some arguments to this method, which would then be
// used to configure transport filters. The types of information passed here
// vary widely. For example, some MSPs may need to configure their transport
// filters with a GUID that indicates which device to use for streaming. This
// info would be passed to the MSP from the TSP via TAPI 3.0 (see sampcall.cpp).
//
HRESULT CSampleMSPStream::ConfigureTransport(void)
{
LOG((MSP_TRACE, "CSampleMSPStream::ConfigureTransport - enter"));
CLock lock(m_lock);
//
// INSERT HERE:
// * create the transport filter(s)
// * configure the transport filter(s) based on passe-in info
// * add filters to our graph
// * if some transport filters always need to be connected together
// (irrespective of what terminals are used, etc.) then they can be
// connected now).
//
m_fTransportConfigured = TRUE;
LOG((MSP_TRACE, "CSampleMSPStream::ConfigureTransport - exit S_OK"));
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// Add the terminal to the graph and connect it to our
// filters, if it is not already in use.
//
HRESULT CSampleMSPStream::ConnectTerminal(ITTerminal * pTerminal)
{
LOG((MSP_TRACE, "CSampleMSPStream::ConnectTerminal - enter"));
//
// Find out the terminal's internal state.
//
TERMINAL_STATE state;
HRESULT hr;
hr = pTerminal->get_State( &state );
if ( FAILED(hr) )
{
LOG((MSP_ERROR, "CSampleMSPStream::ConnectTerminal - "
"get_State on terminal failed - exit 0x%08x", hr));
return hr;
}
//
// If we've already connected the terminal on this stream, then
// there is nothing for us to do. Just assert that the terminal
// also thinks it's connected.
//
if ( m_fTerminalConnected )
{
_ASSERTE( state == TS_INUSE );
LOG((MSP_ERROR, "CSampleMSPStream::ConnectTerminal - "
"terminal already connected on this stream - exit S_OK"));
return S_OK;
}
//
// Otherwise we need to connect the terminal on this call. If the
// terminal is already connected on another call, we must fail. Note
// that since we are making several calls on the terminal here, the
// terminal could become connected on another call while we are
// in the process of doing this. If this happens, the we will just fail
// later.
//
if ( state == TS_INUSE )
{
LOG((MSP_ERROR, "CSampleMSPStream::ConnectTerminal - "
"terminal in use - exit TAPI_E_TERMINALINUSE"));
return TAPI_E_TERMINALINUSE;
}
//
// Get the ITTerminalControl interface.
//
ITTerminalControl * pTerminalControl;
hr = m_Terminals[0]->QueryInterface(IID_ITTerminalControl,
(void **) &pTerminalControl);
if ( FAILED(hr) )
{
LOG((MSP_ERROR, "CSampleMSPStream::ConnectTerminal - "
"QI for ITTerminalControl failed - exit 0x%08x", hr));
return hr;
}
//
// Find out how many pins the terminal has. If not one then bail as
// we have no idea what to do with multiple-pin terminals (we don't
// expose any such terminals from this MSP).
//
DWORD dwNumPinsAvailable;
hr = pTerminalControl->ConnectTerminal(m_pIGraphBuilder,
0,
&dwNumPinsAvailable,
NULL);
if ( FAILED(hr) )
{
LOG((MSP_ERROR, "CSampleMSPStream::ConnectTerminal - "
"query for number of terminal pins failed - exit 0x%08x", hr));
pTerminalControl->Release();
return hr;
}
if ( 1 != dwNumPinsAvailable )
{
LOG((MSP_ERROR, "CSampleMSPStream::ConnectTerminal - "
"unsupported number of terminal pins - exit E_FAIL"));
pTerminalControl->Release();
return E_FAIL;
}
//
// Actually connect the terminal.
//
IPin * pTerminalPin;
hr = pTerminalControl->ConnectTerminal(m_pIGraphBuilder,
0,
&dwNumPinsAvailable,
&pTerminalPin);
if ( FAILED(hr) )
{
pTerminalControl->Release();
LOG((MSP_ERROR, "CSampleMSPStream::ConnectTerminal - "
"ConnectTerminal on terminal failed - exit 0x%08x", hr));
return hr;
}
//
// Make the connection between our filters and the terminal's pin.
//
hr = ConnectToTerminalPin(pTerminalPin);
pTerminalPin->Release();
if ( FAILED(hr) )
{
pTerminalControl->DisconnectTerminal(m_pIGraphBuilder, 0);
pTerminalControl->Release();
LOG((MSP_ERROR, "CSampleMSPStream::ConnectTerminal - "
"ConnectToTerminalPin failed - exit 0x%08x", hr));
return hr;
}
//
// Now we are actually connected. Update our state and perform postconnection
// (ignore postconnection error code).
//
m_fTerminalConnected = TRUE;
pTerminalControl->CompleteConnectTerminal();
pTerminalControl->Release();
LOG((MSP_TRACE, "CSampleMSPStream::ConnectTerminal - exit S_OK"));
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
HRESULT CSampleMSPStream::ConnectToTerminalPin(IPin * pTerminalPin)
{
LOG((MSP_TRACE, "CSampleMSPStream::ConnectToTerminalPin - enter"));
//
// INSERT HERE: Code to connect the terminal's pin to some pin on some
// transport filter belonging to the stream. See the documentation on
// DirectShow in the Windows SDK for help.
//
LOG((MSP_TRACE, "CSampleMSPStream::ConnectToTerminalPin - exit S_OK"));
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// ProcessGraphEvent
//
// Sends an event to the app when we get an event from the filter graph.
// Note: The DirectShow graph events that the MSP cares about will vary
// from MSP to MSP. Be sure to modify this code to correctly propagate the
// events you need, depending on what filters you are using.
//
HRESULT CSampleMSPStream::ProcessGraphEvent(
IN long lEventCode,
IN long lParam1,
IN long lParam2
)
{
LOG((MSP_EVENT, "CSampleMSPStream::ProcessGraphEvent - enter"));
HRESULT hr = S_OK;
switch (lEventCode)
{
case EC_COMPLETE:
hr = FireEvent(CALL_STREAM_INACTIVE, (HRESULT) lParam1, CALL_CAUSE_UNKNOWN);
break;
case EC_USERABORT:
hr = FireEvent(CALL_STREAM_INACTIVE, S_OK, CALL_CAUSE_UNKNOWN);
break;
case EC_ERRORABORT:
case EC_STREAM_ERROR_STOPPED:
case EC_STREAM_ERROR_STILLPLAYING:
case EC_ERROR_STILLPLAYING:
hr = FireEvent(CALL_STREAM_FAIL, (HRESULT) lParam1, CALL_CAUSE_UNKNOWN);
break;
default:
LOG((MSP_EVENT, "CSampleMSPStream::ProcessGraphEvent - "
"ignoring event code %d", lEventCode));
break;
}
if ( FAILED(hr) )
{
LOG((MSP_ERROR, "CSampleMSPStream::ProcessGraphEvent - "
"FireEvent failed - exit 0x%08x", hr));
return hr;
}
LOG((MSP_EVENT, "CSampleMSPStream::ProcessGraphEvent - exit S_OK"));
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// FireEvent
//
// Sends an event to the application.
//
HRESULT CSampleMSPStream::FireEvent(
IN MSP_CALL_EVENT type,
IN HRESULT hrError,
IN MSP_CALL_EVENT_CAUSE cause
)
{
LOG((MSP_EVENT, "CSampleMSPStream::FireEvent - enter"));
//
// Create the event structure.
//
//
// Note:
//
// MSPEVENTITEMs are allocated with AllocateEventItem and freed with
// FreeEventItem
//
// AllocateEventItem takes an optional argument that specifies how many
// extra bytes need to be allocated in addition to the size of MSPEVENTITEM
//
MSPEVENTITEM * pEventItem = AllocateEventItem();
if (pEventItem == NULL)
{
LOG((MSP_ERROR, "CSampleMSPStream::FireEvent - "
"can't create MSPEVENTITEM structure - exit E_OUTOFMEMORY"));
return E_OUTOFMEMORY;
}
//
// Fill in the necessary fields for the event structure.
//
pEventItem->MSPEventInfo.dwSize = sizeof(MSP_EVENT_INFO);
pEventItem->MSPEventInfo.Event = ME_CALL_EVENT;
ITTerminal * pTerminal = NULL;
if ( 0 != m_Terminals.GetSize() )
{
_ASSERTE( 1 == m_Terminals.GetSize() );
pTerminal = m_Terminals[0];
pTerminal->AddRef();
}
ITStream * pStream = (ITStream *) this;
pStream->AddRef();
pEventItem->MSPEventInfo.MSP_CALL_EVENT_INFO.Type = type;
pEventItem->MSPEventInfo.MSP_CALL_EVENT_INFO.Cause = cause;
pEventItem->MSPEventInfo.MSP_CALL_EVENT_INFO.pStream = pStream;
pEventItem->MSPEventInfo.MSP_CALL_EVENT_INFO.pTerminal = pTerminal;
pEventItem->MSPEventInfo.MSP_CALL_EVENT_INFO.hrError = hrError;
#ifdef MSPLOG
//
// Spew some debug output to indicate what this is.
//
char * pszType;
DWORD dwLevel;
switch (type)
{
case CALL_NEW_STREAM:
pszType = "CALL_NEW_STREAM (unexpected)";
dwLevel = MSP_ERROR;
break;
case CALL_STREAM_FAIL:
pszType = "CALL_STREAM_FAIL";
dwLevel = MSP_INFO;
break;
case CALL_TERMINAL_FAIL:
pszType = "CALL_TERMINAL_FAIL";
dwLevel = MSP_INFO;
break;
case CALL_STREAM_NOT_USED:
pszType = "CALL_STREAM_NOT_USED (unexpected)";
dwLevel = MSP_ERROR;
break;
case CALL_STREAM_ACTIVE:
pszType = "CALL_STREAM_ACTIVE";
dwLevel = MSP_INFO;
break;
case CALL_STREAM_INACTIVE:
pszType = "CALL_STREAM_INACTIVE";
dwLevel = MSP_INFO;
break;
default:
pszType = "UNKNOWN EVENT TYPE";
dwLevel = MSP_ERROR;
break;
}
LOG((dwLevel, "CSampleMSPStream::FireEvent - "
"EVENT DUMP: type = %s", pszType));
LOG((dwLevel, "CSampleMSPStream::FireEvent - "
"EVENT DUMP: pStream = %p", pStream));
LOG((dwLevel, "CSampleMSPStream::FireEvent - "
"EVENT DUMP: pTerminal = %p", pTerminal));
LOG((dwLevel, "CSampleMSPStream::FireEvent - "
"EVENT DUMP: hrError = %08x", hrError));
#endif // ifdef MSPLOG
//
// Send the event to the app.
//
HRESULT hr = m_pMSPCall->HandleStreamEvent(pEventItem);
if (FAILED(hr))
{
LOG((MSP_ERROR, "CSampleMSPStream::FireEvent - "
"HandleStreamEvent failed - returning 0x%08x", hr));
pStream->Release();
pTerminal->Release();
//
// Note:
//
// MSPEVENTITEMs are allocated with AllocateEventItem and freed with
// FreeEventItem
//
FreeEventItem(pEventItem);
pEventItem = NULL;
return hr;
}
LOG((MSP_EVENT, "CSampleMSPStream::FireEvent - exit S_OK"));
return S_OK;
}
// eof