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

367 lines
9.3 KiB
C++

//*****************************************************************************
//
// Microsoft Windows Media
// Copyright (C) Microsoft Corporation. All rights reserved.
//
// FileName: Reader.cpp
//
// Abstract: Implementation of class CReader, which provides the
// functionality of reading from an IStream.
//
//*****************************************************************************
#include "stdafx.h"
#include "Reader.h"
#include "ROStream.h"
//------------------------------------------------------------------------------
// Name: CReader()
// Desc: Constructor.
//------------------------------------------------------------------------------
CReader::CReader()
{
m_cRef = 1;
m_pReader = NULL;
m_pReader2 = NULL;
m_hEvent = INVALID_HANDLE_VALUE;
m_pStream = NULL;
m_hrAsync = S_OK;
}
//------------------------------------------------------------------------------
// Name: ~CReader()
// Desc: Destructor.
//------------------------------------------------------------------------------
CReader::~CReader()
{
SAFE_RELEASE( m_pReader );
SAFE_RELEASE( m_pReader2 );
SAFE_RELEASE( m_pStream );
if( NULL != m_hEvent )
{
CloseHandle( m_hEvent );
m_hEvent = INVALID_HANDLE_VALUE;
}
}
//------------------------------------------------------------------------------
// Implementation of IUnknown methods
//------------------------------------------------------------------------------
HRESULT STDMETHODCALLTYPE CReader::QueryInterface( /* [in] */ REFIID riid,
/* [out] */ void __RPC_FAR *__RPC_FAR *ppvObject )
{
if( ( IID_IWMReaderCallback == riid ) ||
( IID_IUnknown == riid ) )
{
*ppvObject = static_cast< IWMReaderCallback* >( this );
AddRef();
return( S_OK );
}
*ppvObject = NULL;
return( E_NOINTERFACE );
}
ULONG STDMETHODCALLTYPE CReader::AddRef()
{
return( InterlockedIncrement( &m_cRef ) );
}
ULONG STDMETHODCALLTYPE CReader::Release()
{
if( 0 == InterlockedDecrement( &m_cRef ) )
{
delete this;
return( 0 );
}
return( m_cRef );
}
//------------------------------------------------------------------------------
// Name: CReader::OnSample()
// Desc: Implementation of IWMReaderCallback::OnSample.
//------------------------------------------------------------------------------
HRESULT CReader::OnSample( /* [in] */ DWORD dwOutputNum,
/* [in] */ QWORD cnsSampleTime,
/* [in] */ QWORD cnsSampleDuration,
/* [in] */ DWORD dwFlags,
/* [in] */ INSSBuffer __RPC_FAR *pSample,
/* [in] */ void __RPC_FAR *pvContext )
{
//
// Add your code here
//
return( S_OK );
}
//------------------------------------------------------------------------------
// Name: CReader::OnStatus()
// Desc: Implementation of IWMStatusCallback::OnStatus.
//------------------------------------------------------------------------------
HRESULT CReader::OnStatus( /* [in] */ WMT_STATUS Status,
/* [in] */ HRESULT hr,
/* [in] */ WMT_ATTR_DATATYPE dwType,
/* [in] */ BYTE __RPC_FAR *pValue,
/* [in] */ void __RPC_FAR *pvContext )
{
switch( Status )
{
case WMT_OPENED:
m_hrAsync = hr;
SetEvent( m_hEvent );
printf( "Opened the file ...\n" );
break;
case WMT_STARTED:
m_hrAsync = hr;
SetEvent( m_hEvent );
printf( "Started ...\n" );
break;
case WMT_STOPPED:
m_hrAsync = hr;
SetEvent( m_hEvent );
printf( "Stopped ...\n" );
break;
case WMT_CLOSED:
m_hrAsync = hr;
SetEvent( m_hEvent );
printf( "Closed the file ...\n" );
break;
case WMT_EOF:
m_hrAsync = hr;
SetEvent( m_hEvent );
printf( "End of file ...\n" );
break;
}
return( S_OK );
}
//------------------------------------------------------------------------------
// Name: CReader::Open()
// Desc: Creates the reader and opens the file.
//------------------------------------------------------------------------------
HRESULT CReader::Open( /* [in] */ const TCHAR *ptszFile )
{
HRESULT hr = S_OK;
do
{
m_hrAsync = S_OK;
if( NULL == m_pStream )
{
m_pStream = new CROStream;
if( NULL == m_pStream )
{
hr = E_OUTOFMEMORY;
break;
}
}
//
// Open input file
//
hr = m_pStream->Open( ptszFile );
if( FAILED( hr ) )
{
break;
}
//
// Create the event handle as automatic reset; initial state is not set.
//
if( INVALID_HANDLE_VALUE == m_hEvent )
{
m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
if( NULL == m_hEvent )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
printf( "Could not Create Event. (hr=%#X)\n", hr );
break;
}
}
ResetEvent( m_hEvent );
//
// Create reader object
//
SAFE_RELEASE( m_pReader );
SAFE_RELEASE( m_pReader2 );
hr = WMCreateReader( NULL, WMT_RIGHT_PLAYBACK, &m_pReader );
if( FAILED( hr ) )
{
printf( "Could not create reader (hr=%#X).\n", hr );
break;
}
//
// QI for IWMReaderAdvanced2
//
hr = m_pReader->QueryInterface( IID_IWMReaderAdvanced2, ( void** )&m_pReader2 );
if( FAILED( hr ) )
{
printf( "Could not QI for IWMReaderAdvanced2 (hr=%#X).\n", hr );
break;
}
//
// Open the stream
//
hr = m_pReader2->OpenStream( m_pStream, this, NULL );
if( FAILED( hr ) )
{
printf( "Could not open reader from stream (hr=%#X).\n", hr );
break;
}
//
// Wait for the open to finish
//
hr = WaitForEvent();
if( FAILED( hr ) )
{
printf( "Stream open failed (hr=%#X).\n", hr );
break;
}
//
// Check open operation result
//
if( FAILED( m_hrAsync ) )
{
hr = m_hrAsync;
printf( "Open failed (hr=%#X).\n", m_hrAsync );
break;
}
}
while( FALSE );
return( hr );
}
//------------------------------------------------------------------------------
// Name: CReader::Start()
// Desc: Plays the file.
//------------------------------------------------------------------------------
HRESULT CReader::Start()
{
HRESULT hr = S_OK;
if( NULL == m_pReader )
{
return( E_UNEXPECTED );
}
//
// Start the reader to play the stream normally
//
m_hrAsync = S_OK;
hr = m_pReader->Start( 0, 0, 1.0, NULL );
if( FAILED( hr ) )
{
printf( "Could not start IWMReader (hr=%#X).\n", hr );
return( hr );
}
printf( "Playing......\n" );
//
// Wait until all data has been sent to output.
// We don't know the file's duration, so simply wait forever and hope for the best.
// In a real application, you might want to query for the file's duration.
//
hr = WaitForEvent( INFINITE );
if( FAILED( hr ) )
{
printf( "Read operation failed (hr=%#X).\n", hr );
return( hr );
}
//
// Check playback results
//
if( FAILED( m_hrAsync ) )
{
printf( "IWMReader playback failed (hr=%#X).\n", m_hrAsync );
return( hr );
}
printf( "Playback finished.\n" );
return( S_OK );
}
//------------------------------------------------------------------------------
// Name: CReader::Close()
// Desc: Closes the reader.
//------------------------------------------------------------------------------
HRESULT CReader::Close()
{
HRESULT hr = S_OK;
if( NULL == m_pReader )
{
return( S_FALSE );
}
hr = m_pReader->Close();
if( FAILED ( hr ) )
{
printf( "Could not close Reader (hr=%#X).\n", hr );
return hr;
}
hr = WaitForEvent();
if( FAILED( hr ) )
{
printf( "Close operation failed (hr=%#X).\n", hr );
return( hr );
}
return( hr );
}
//------------------------------------------------------------------------------
// Name: CReader::WaitForEvent()
// Desc: Waits for the event to be signaled.
//------------------------------------------------------------------------------
HRESULT CReader::WaitForEvent( /* [in] */ DWORD msWait )
{
DWORD dwRet = 0;
DWORD dwLastError = 0;
HRESULT hr = S_OK;
dwRet = WaitForSingleObject( m_hEvent, msWait );
if( WAIT_OBJECT_0 == dwRet )
{
return( S_OK );
}
if( WAIT_TIMEOUT == dwRet )
{
printf( "Time out waiting for the event.\n" );
return( HRESULT_FROM_WIN32( WAIT_TIMEOUT ) );
}
if( WAIT_FAILED == dwRet )
{
dwLastError = GetLastError();
printf( "WaitForSingleObject() failed (LastError=%ld).\n", dwLastError );
return( HRESULT_FROM_WIN32( dwLastError ) );
}
return( S_OK );
}