//========================================================================
//TITLE:
// CMedia更新至v1.4.3
//AUTHOR:
// norains
//DATE:
// Friday 27-July-2007
//Environment:
// EVC4.0 + Windows CE 5.0 Standard SDK
//========================================================================
相对v1.2.0版本进行的改进:
1.增加GetMediaProperty函数获得的属性,增加如下属性:llDuration,llAvailableEarliest,llAvailableLatest.
2.增加如下函数:SetRate(),GetRate(),GetPositionCurrent(),SetPositionCurrent() ,GetDisplayMode()
3.改进之前一些函数的HRESULT值返回BOOL值的判定方法
4.增加SetVideoWindow()一个参数,以设置可以在窗口的任意位置为起点播放视频
5.改进SetDisplayMode()函数,当窗口句柄为空时,设置播放区域为0,并返回FALSE
6.改进SetNotifyWindow()函数,令其能够接收普通的窗口消息
7.Open()的参数改为const类型,更符合实际意义
v1.2.0版本及相关用法见:http://blog.csdn.net/norains/archive/2007/05/14/1609118.aspx
我们来看看具体更新了哪些功能:
1.MEDIAPROPERTY
增加了llDuration,llAvailableEarliest,llAvailableLatest属性,分别代表影片的时间长度,最早的可拖拽的时间位置,最早的可拖拽的时间位置.这个属性可以用在GetMediaProperty()函数中.
2.SetRate(),GetRate()
SetRate()设置当前的播放速率,"1"为正常速率,"2"即为两倍速,以此类推.
GetRate()获取当前播放的速率.
3.GetPositionCurrent(),SetPositionCurrent()
GetPositionCurrent():获取当前的时间位置,返回的时间值以100ns为基本单位.
SetPositionCurrent():设置播放的时间位置,该范围必须是llAvailableEarliest和llAvailableLatest之间的数值.
4.GetDisplayMode()
该函数用来获取当前的播放模式.
v1.4.3的完整代码如下:
///////////////////////////////////////////////////////////////////// //
// Media.h: interface for the CMedia class.
//
// Version:
// 1.4.3
// Date:
// 2007.07.19
///////////////////////////////////////////////////////////////////// /
#ifndef MEDIA_H
#define MEDIA_H
#include < mmsystem.h >
#include < streams.h >
// --------------------------------------------------------------------
// Macro define
// The volume value
#define MAX_VOLUME 0
#define MIN_VOLUME -10000
// The balance value
#define MAX_BALANCE 10000
#define MIN_BALANCE -10000
// The flag means that the area is the whole window
const RECT RC_WHOLE_WINDOWN_AREA = { 0 , 0 , 0 , 0 };
// --------------------------------------------------------------------
// Enum value
enum DISPLAYMODE
{
// Fit to the play window size. How wide (height) the window is, how
// is the move. Keep aspect ratio.
DISP_FIT,
// Not support.Stretch to the play window size. Don't keep the aspect ratio.
DISP_STRETCH,
// Full screen play.
DISP_FULLSCREEN,
// When the size of video is smaller than the play window, it displayes
// as the video size. If it's bigger , it just like the DISP_FIT mode.
DISP_NATIVE
};
// --------------------------------------------------------------------
// The media file property
typedef struct
{
// The volume range is –10,000 to 0.
// Divide by 100 to get equivalent decibel value (for example –10,000 = –100 dB).
LONG lVolume;
// The value from –10,000 to 10,000 indicating the stereo balance
// As with the Volume property, units correspond to .01 decibels (multiplied by –1 when plBalance is a positive value).
// For example, a value of 1000 indicates –10 dB on the right channel and –90 dB on the left channel.
LONG lBalance;
// Width of the video
LONG lWidth;
// Height of the video
LONG lHeight;
// Approximate bit rate
LONG lBitRate;
// The length of time that the media stream will play.
// The duration assumes normal playback speed, and it is therefore unaffected by the rate
LONGLONG llDuration;
// Earliest time that can be efficiently seeked to.
LONGLONG llAvailableEarliest;
// Latest time that can be efficiently seeked to
LONGLONG llAvailableLatest;
}MEDIAPROPERTY, * PMEDIAPROPERTY;
// --------------------------------------------------------------------
class CMedia
{
public :
DISPLAYMODE GetDisplayMode();
BOOL SetPositionCurrent(LONGLONG llPos);
BOOL GetPositionCurrent(LONGLONG * pllPos);
BOOL GetRate( double * pdRate);
BOOL SetRate( double dRate);
BOOL GetEvent(LONG * plEvCode, LONG * plParam1, LONG * plParam2);
BOOL SetNotifyWindow(HWND hWnd, UINT wMsg, long lInstanceData);
BOOL SetVolume(LONG lVolume, LONG lBalance = 0 );
BOOL SetDisplayMode(DISPLAYMODE mode);
BOOL GetMediaProperty(PMEDIAPROPERTY pOutProperty);
static CMedia * GetInstance();
void Close();
BOOL CheckVisibility();
BOOL SetVideoWindow(HWND hWndVideo, const RECT & rcDisp = RC_WHOLE_WINDOWN_AREA);
BOOL Open( const TCHAR * pcszFileName);
BOOL Stop();
BOOL Pause();
BOOL Play();
virtual ~ CMedia();
protected :
CMedia();
// Collection of interfaces
IGraphBuilder * m_pGB;
IMediaControl * m_pMC;
IMediaEventEx * m_pME;
IVideoWindow * m_pVW;
IBasicAudio * m_pBA;
IBasicVideo * m_pBV;
IMediaSeeking * m_pMS;
TCHAR m_szFileName[MAX_PATH];
HWND m_hWndVideo; // The window play video
HWND m_hWndNotify; // The window notify
BOOL m_bExitThrd;
BOOL m_bThrdRunning;
static CMedia * m_pInstance;
DISPLAYMODE m_DispMode;
DWORD m_dwCapability;
RECT m_rcDisp;
};
#endif // #ifndef MEDIA_H
///////////////////////////////////////////////////////////////////// //
// Media.cpp: implementation of the CMedia class.
//
///////////////////////////////////////////////////////////////////// /
#include " stdafx.h "
#include " Media.h "
// ========================================================================================================
// Link the .lib
// The lib also is copy from "(InstallDir)WINCE500PUBLICDIRECTXSDKLIB"
#pragma comment (lib,"Ole32.lib")
#ifdef CPU_X86EM
#pragma comment (lib,"./lib/X86em/Strmiids.lib")
#pragma comment (lib,"./lib/X86em/Strmbase.lib")
#endif
#ifdef CPU_MIPSII
#pragma comment (lib,"./lib/MIPSII/Strmiids.lib")
#pragma comment (lib,"./lib/MIPSII/Strmbase.lib")
#endif
#ifdef CPU_ARM4I
#pragma comment (lib,"./lib/ARM4I/Strmiids.lib")
#pragma comment (lib,"./lib/ARM4I/Strmbase.lib")
#endif
// ========================================================================================================
// ----------------------------------------------------------------------------------------------
// Macro define
// Default play mode
#define DEFAULT_DISPLAY_MODE DISP_NATIVE
// ----------------------------------------------------------------------
// Initialize
CMedia * CMedia::m_pInstance = NULL;
// ------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////// /
// Construction/Destruction
///////////////////////////////////////////////////////////////////// /
CMedia::CMedia():
m_pGB(NULL),
m_pMC(NULL),
m_pME(NULL),
m_pVW(NULL),
m_pBA(NULL),
m_pBV(NULL),
m_pMS(NULL),
m_hWndVideo(NULL),
m_bExitThrd(TRUE),
m_bThrdRunning(FALSE),
m_DispMode(DEFAULT_DISPLAY_MODE),
m_hWndNotify(NULL),
m_rcDisp(RC_WHOLE_WINDOWN_AREA)
{
memset(m_szFileName, 0 , sizeof (m_szFileName));
}
CMedia:: ~ CMedia()
{
if (m_pInstance != NULL)
{
delete m_pInstance;
m_pInstance = NULL;
}
}
// ------------------------------------------------------------
// Description:
// Play the media file
// When you call the function,you should call Open() before.
//
// -------------------------------------------------------------
BOOL CMedia::Play()
{
// Run the graph to play the media file
if (m_pMC == NULL)
{
return FALSE;
}
return SUCCEEDED(m_pMC -> Run());
}
// ------------------------------------------------------------
// Description:
// Pause.
// When you call the function,you should call Open() before.
//
// -------------------------------------------------------------
BOOL CMedia::Pause()
{
if (m_pMC == NULL)
{
return FALSE;
}
return SUCCEEDED(m_pMC -> Pause());
}
// ------------------------------------------------------------
// Description:
// Stop.
// When you call the function,you should call Open() before.
//
// -------------------------------------------------------------
BOOL CMedia::Stop()
{
if (m_pMC == NULL || m_pMS == NULL)
{
return FALSE;
}
HRESULT hr;
hr = m_pMC -> Stop();
SetPositionCurrent( 0 );
return SUCCEEDED(hr);
}
// --------------------------------------------------------------------------
// Description:
// Open the media file. When succeed in calling the function ,
// you should call the Close() to release the resource
//
// -------------------------------------------------------------------------
BOOL CMedia::Open( const TCHAR * pcszFileName)
{
BOOL bResult = FALSE;
if (_tcslen(pcszFileName) >= MAX_PATH)
{
goto END;
}
else
{
_tcscpy(m_szFileName,pcszFileName);
// Check the file existing
HANDLE hdFile = CreateFile(m_szFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);
if (hdFile == INVALID_HANDLE_VALUE)
{
// The file doesn't exist
goto END;
}
else
{
CloseHandle(hdFile);
}
}
// Initialize COM
if (CoInitializeEx(NULL, COINIT_MULTITHREADED) != S_OK)
{
goto END;
}
// Get the interface for DirectShow's GraphBuilder
if (CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, ( void ** ) & m_pGB) != S_OK)
{
goto END;
}
// Have the graph construct its the appropriate graph automatically
if (m_pGB -> RenderFile(m_szFileName, NULL) != NOERROR)
{
goto END;
}
// QueryInterface for DirectShow interfaces
if (m_pGB -> QueryInterface(IID_IMediaControl, ( void ** ) & m_pMC) != NOERROR)
{
goto END;
}
if (m_pGB -> QueryInterface(IID_IMediaEventEx, ( void ** ) & m_pME) != NOERROR)
{
goto END;
}
if (m_pGB -> QueryInterface(IID_IMediaSeeking, ( void ** ) & m_pMS) != NOERROR)
{
goto END;
}
// Query for video interfaces, which may not be relevant for audio files
if (m_pGB -> QueryInterface(IID_IVideoWindow, ( void ** ) & m_pVW) != NOERROR)
{
goto END;
}
if (m_pGB -> QueryInterface(IID_IBasicVideo, ( void ** ) & m_pBV) != NOERROR)
{
goto END;
}
if (CheckVisibility() == FALSE)
{
// It just be the audio file, and don't need video filter.
// Relinquish ownership (IMPORTANT!) after hiding
if (m_pVW != NULL)
{
m_pVW -> put_Visible(OAFALSE);
m_pVW -> put_Owner(NULL);
}
if (m_pBV != NULL)
{
m_pBV -> Release();
m_pBV = NULL;
}
if (m_pVW != NULL)
{
m_pVW -> Release();
m_pVW = NULL;
}
}
// Query for audio interfaces, which may not be relevant for video-only files
if (m_pGB -> QueryInterface(IID_IBasicAudio, ( void ** ) & m_pBA) != NOERROR)
{
goto END;
}
// Set play mode
SetDisplayMode(m_DispMode);
// Get the capabilities of the media file.
m_pMS -> GetCapabilities( & m_dwCapability);
bResult = TRUE;
END:
if (bResult == FALSE)
{
// Release the resource
Close();
}
return bResult;
}
// ------------------------------------------------------------
// Description:
// This method sets an owning parent for the video window.
//
// Parameters:
// hWnd : [in] Handle of new owner window.
// rcDisp: [in] The display area. If the parameter is not set,
// it will be set as RC_WHOLE_WINDOWN_AREA which means thai
// the whole window is for displaying the video.
//
// ----------------------------------------------------------
BOOL CMedia::SetVideoWindow(HWND hWndVideo, const RECT & rcDisp)
{
m_hWndVideo = hWndVideo;
m_rcDisp = rcDisp;
if (m_pVW == NULL)
{
return FALSE;
}
if (FAILED(m_pVW -> put_Owner((OAHWND)hWndVideo)))
{
return FALSE;
}
if (FAILED(m_pVW -> put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)))
{
return FALSE;
}
// Set play mode in order to notify the displayed area
return SetDisplayMode(m_DispMode);
}
// ------------------------------------------------------------
// Description:
// Check the file visibility
// When you call the function,you should call Open() before.
//
// Parameters:
// TRUE: Video
// FALSE: It's not the video
//
// ------------------------------------------------------------
BOOL CMedia::CheckVisibility()
{
if ( ! m_pVW)
{
// No VideoWindow interface. Assuming audio/MIDI file or unsupported video codec
return FALSE;
}
if ( ! m_pBV)
{
// No BasicVideo interface. Assuming audio/MIDI file or unsupported video codec.
return FALSE;
}
// If this is an audio-only clip, get_Visible() won't work.
//
// Also, if this video is encoded with an unsupported codec,
// we won't see any video, although the audio will work if it is
// of a supported format.
long lVisible;
return SUCCEEDED(m_pVW -> get_Visible( & lVisible));
}
// ------------------------------------------------------------
// Description:
// Release the resource which opened in the Open()
//
// ------------------------------------------------------------
void CMedia::Close()
{
// Relinquish ownership (IMPORTANT!) after hiding
if (m_pVW != NULL)
{
m_pVW -> put_Visible(OAFALSE);
m_pVW -> put_Owner(NULL);
}
if (m_pMC != NULL)
{
m_pMC -> Release();
m_pMC = NULL;
}
if (m_pME != NULL)
{
m_pME -> SetNotifyWindow(NULL,NULL,NULL);
m_pME -> Release();
m_pME = NULL;
}
if (m_pMS != NULL)
{
m_pMS -> Release();
m_pMS = NULL;
}
if (m_pBV != NULL)
{
m_pBV -> Release();
m_pBV = NULL;
}
if (m_pBA != NULL)
{
m_pBA -> Release();
m_pBA = NULL;
}
if (m_pVW != NULL)
{
m_pVW -> Release();
m_pVW = NULL;
}
if (m_pGB != NULL)
{
m_pGB -> Release();
m_pGB = NULL;
}
// Finished with COM
memset(m_szFileName, 0 , sizeof (m_szFileName));
CoUninitialize();
}
// ------------------------------------------------------------
// Description:
// Get the instance of object
//
// ------------------------------------------------------------
CMedia * CMedia::GetInstance()
{
if (m_pInstance == NULL)
{
m_pInstance = new CMedia();
}
return m_pInstance;
}
// ------------------------------------------------------------
// Description:
// Get the media file property.
// When you call the function,you should call Open() before.
//
// ------------------------------------------------------------
BOOL CMedia::GetMediaProperty(PMEDIAPROPERTY pOutProperty)
{
MEDIAPROPERTY prop = { 0 };
if (m_pBA == NULL && m_pBV == NULL && m_pMS == NULL)
{
return FALSE;
}
// Get the audio property
if (m_pBA != NULL)
{
m_pBA -> get_Volume( & prop.lVolume);
m_pBA -> get_Balance( & prop.lBalance);
}
// Get the video property
if (CheckVisibility() == TRUE && m_pBV != NULL)
{
m_pBV -> get_BitRate( & prop.lBitRate);
m_pBV -> GetVideoSize( & prop.lWidth, & prop.lHeight);
}
// Get the seeking property
if (m_pMS != NULL)
{
m_pMS -> GetDuration( & prop.llDuration);
m_pMS -> GetAvailable( & prop.llAvailableEarliest, & prop.llAvailableLatest);
}
* pOutProperty = prop;
return TRUE;
}
// ------------------------------------------------------------
// Description:
// Set the display mode.
// When you call the function,you should call SetVideoWindow() before.
// If the parent windows (m_hWndVideo) is NULL, the display area would be set to zero.
//
// ------------------------------------------------------------
BOOL CMedia::SetDisplayMode(DISPLAYMODE mode)
{
if (m_pVW == NULL)
{
return FALSE;
}
if (m_hWndVideo == NULL)
{
m_pVW -> put_Left( 0 );
m_pVW -> put_Top( 0 );
m_pVW -> put_Width( 0 );
m_pVW -> put_Height( 0 );
return FALSE;
}
m_DispMode = mode;
if (mode == DISP_FULLSCREEN)
{
m_pVW -> put_FullScreenMode(OATRUE);
}
else
{
// Restore to the normal mode
m_pVW -> put_FullScreenMode(OAFALSE);
RECT rcWnd = m_rcDisp;
if (rcWnd.left == RC_WHOLE_WINDOWN_AREA.left &&
rcWnd.top == RC_WHOLE_WINDOWN_AREA.top &&
rcWnd.right == RC_WHOLE_WINDOWN_AREA.right &&
rcWnd.bottom == RC_WHOLE_WINDOWN_AREA.bottom )
{
GetClientRect(m_hWndVideo, & rcWnd);
}
LONG lWndWidth = rcWnd.right - rcWnd.left;
LONG lWndHeight = rcWnd.bottom - rcWnd.top;
MEDIAPROPERTY prop = { 0 };
GetMediaProperty( & prop);
if (mode == DISP_FIT || mode == DISP_NATIVE)
{
LONG lDispLeft,lDispTop,lDispWidth,lDispHeight;
if (mode == DISP_NATIVE && lWndWidth >= prop.lWidth && lWndHeight >= prop.lHeight)
{
lDispLeft = (lWndWidth - prop.lWidth) / 2 + rcWnd.left;
lDispTop = (lWndHeight - prop.lHeight) / 2 + rcWnd.top;
lDispWidth = prop.lWidth ;
lDispHeight = prop.lHeight ;
}
else
{
if (prop.lWidth * lWndHeight > lWndWidth * prop.lHeight)
{
lDispWidth = lWndWidth;
lDispHeight = (LONG)(( float )lDispWidth / ( float )prop.lWidth * prop.lHeight);
lDispLeft = rcWnd.left;
lDispTop = (lWndHeight - lDispHeight) / 2 + rcWnd.top;
}
else if (prop.lWidth * lWndHeight < lWndWidth * prop.lHeight)
{
lDispHeight = lWndHeight;
lDispWidth = (LONG)(( float )lDispHeight / ( float )prop.lHeight * prop.lWidth);
lDispLeft = (lWndWidth - lDispWidth) / 2 + rcWnd.left;
lDispTop = rcWnd.top;
}
else
{
lDispWidth = lWndWidth;
lDispHeight = lWndHeight;
lDispLeft = rcWnd.left;
lDispTop = rcWnd.top;
}
}
m_pVW -> put_Left(lDispLeft);
m_pVW -> put_Top(lDispTop);
m_pVW -> put_Width(lDispWidth);
m_pVW -> put_Height(lDispHeight);
}
else if (mode == DISP_STRETCH)
{
m_pVW -> put_Left(rcWnd.left);
m_pVW -> put_Top(rcWnd.top);
m_pVW -> put_Width(lWndWidth);
m_pVW -> put_Height(lWndHeight);
}
}
return TRUE;
}
// ------------------------------------------------------------
// Description:
// Set the volume.
// When you call the function,you should call Open() before.
//
// Parameters:
// lVolume:[in] The volume (amplitude) of the audio signal.
// Range is –10,000 to 0.
// lBalance:[in] The balance for the audio signal. Default value is 0.
// The value from –10,000 to 10,000 indicating the stereo balance.
//
// ------------------------------------------------------------
BOOL CMedia::SetVolume(LONG lVolume, LONG lBalance)
{
if (m_pBA == NULL)
{
return FALSE;
}
if (lVolume < MIN_VOLUME && lVolume > MAX_VOLUME && lBalance < MIN_BALANCE && lBalance > MAX_BALANCE)
{
return FALSE;
}
m_pBA -> put_Volume(lVolume);
m_pBA -> put_Balance(lBalance);
return TRUE;
}
// ----------------------------------------------------------------------
// Description:
// Registers a window that will handle the notified message when a specified event occurs and some window message
//
// Parameters:
// hWnd:[in] Handle of window to notify. Pass NULL to stop notification.
// wMsg:[in] Window message to be passed as the notification.
// lInstanceData:[in] Value (instance data) to be passed as the lParam parameter for the lMsg message.
//
// Remarks:
// When the notified window receive the wMsg as the notification, you could get the event code.
// The follow codes show that process:
//
// // "WM_GRAPHNOTIFY" is the user-define notified message
// case WM_GRAPHNOTIFY:
// {
// LONG evCode,evParam1,evParam2;
//
// // "m_pMedia" is the instance of the CMedia
// if(m_pMedia->GetEvent(&evCode,&evParam1,&evParam2) == TRUE)
// {
// // Check the event code
// if(evCode == EC_COMPLETE)
// {
// // Do something
// }
// }
// return 0;
// }
//
// The event code is as follow:
// EC_ACTIVATE An audio or video renderer is losing or gaining activation.
// EC_BUFFERING_DATA The buffering status is changing.
// EC_CLOCK_CHANGED The filter graph has changed from one reference clock to another.
// EC_COMPLETE All data has been rendered.
// EC_DRM_LEVEL Notifies when content protected by digital rights management (DRM) requests some form of analog content protection.
// EC_END_OF_SEGMENT Notifies that a segment end has been reached.
// EC_ERROR_STILLPLAYING At least one call to Run failed in an active filter graph.
// The current state of any underlying filter graph or graphs is indeterminate; they might be running, but some are almost certainly not.
// EC_ERRORABORT An error forced the termination of a requested operation.
// EC_FULLSCREEN_LOST The video renderer is switching out of full-screen mode.
// EC_NEED_RESTART The current graph must be stopped and restarted.
// EC_NOTIFY_WINDOW Pass the window handle around during pin connection.
// EC_OLE_EVENT A filter is passing a text string to the application.
// EC_OPENING_FILE The open file status is changing.
// EC_PALETTE_CHANGED The video palette has changed.
// EC_QUALITY_CHANGE The playback quality has changed.
// EC_REPAINT A repaint is required.
// EC_SEGMENT_STARTED Notifies that a new segment has been started.
// EC_SHUTTING_DOWN The filter graph is starting to shut down.
// DirectShow passes this notification to any plug-in distributors that support the IMediaEventSink interface.
// EC_STARVATION One of the filters (usually a parser or file source filter) is not receiving enough data.
// By default, the filter graph manager will pause all running filters and then return to normal operation when enough data is available.
// EC_STREAM_CONTROL_STARTED The starting reference time from an earlier call to IAMStreamControl::StartAt passed.
// EC_STREAM_CONTROL_STOPPED The stopping reference time from an earlier call to IAMStreamControl::StopAt passed.
// EC_STREAM_ERROR_STILLPLAYING The stream is still playing, but should not be playing.
// EC_STREAM_ERROR_STOPPED The stream has stopped, but should not have stopped.
// EC_TIME The requested reference time occurred.
// EC_USERABORT A user has forced the termination of a requested operation.
// EC_VIDEO_SIZE_AR_CHANGED The size or aspect ratio of the native video has changed.
// EC_VIDEO_SIZE_CHANGED The size of the native video has changed.
// EC_WINDOW_DESTROYED The video renderer's filter is being removed or destroyed.
//
//
//
// DirectShow passes the following messages to the window specified by the hWnd parameter,
// if and when the application generates them:
// WM_KEYDOWN
// WM_KEYUP
// WM_LBUTTONDBLCLK
// WM_LBUTTONDOWN
// WM_LBUTTONUP
// WM_MBUTTONDBLCLK
// WM_MBUTTONDOWN
// WM_MBUTTONUP
// WM_MOUSEACTIVATE
// WM_MOUSEMOVE
// WM_RBUTTONDBLCLK
// WM_RBUTTONDOWN
// WM_RBUTTONUP
// -----------------------------------------------------------------------------
BOOL CMedia::SetNotifyWindow(HWND hWnd, UINT wMsg, long lInstanceData)
{
if (m_pME == NULL)
{
return FALSE;
}
HRESULT hr;
hr = m_pME -> SetNotifyWindow((OAHWND)hWnd,wMsg,lInstanceData);
if (FAILED(hr))
{
return FALSE;
}
if (CheckVisibility() == TRUE && m_pVW != NULL)
{
hr = m_pVW -> put_MessageDrain((OAHWND)hWnd);
}
return SUCCEEDED(hr);
}
// ----------------------------------------------------------------------
// Description:
// This method retrieves the notification event.
//
// -----------------------------------------------------------------------
BOOL CMedia::GetEvent(LONG * plEvCode, LONG * plParam1, LONG * plParam2)
{
if (m_pME == NULL)
{
return FALSE;
}
LONG evCode, evParam1, evParam2;
if (SUCCEEDED(m_pME -> GetEvent( & evCode, & evParam1, & evParam2, 0 )) == TRUE)
{
* plEvCode = evCode;
* plParam1 = evParam1;
* plParam2 = evParam2;
// Spin through the events
m_pME -> FreeEventParams(evCode, evParam1, evParam2);
}
else
{
return FALSE;
}
return TRUE;
}
// ----------------------------------------------------------------------
// Description:
// This method sets a new playback rate.
//
// Parameters
// dRate:[in] New rate, where 1 is the normal rate, 2 is twice as fast, and so on.
// -----------------------------------------------------------------------
BOOL CMedia::SetRate( double dRate)
{
if (m_pMS == NULL)
{
return FALSE;
}
return SUCCEEDED(m_pMS -> SetRate(dRate));
}
// ----------------------------------------------------------------------
// Description:
// This method retrieves the current rate.
//
// Parameters:
// pdRate:[out] The rate
// -----------------------------------------------------------------------
BOOL CMedia::GetRate( double * pdRate)
{
if (m_pMS == NULL)
{
return FALSE;
}
return SUCCEEDED(m_pMS -> GetRate(pdRate));
}
// ----------------------------------------------------------------------
// Description:
// This method retrieves the current position in terms of the total length of the media stream
//
// Parameters:
// pllPos:[out]Current position.
// -----------------------------------------------------------------------
BOOL CMedia::GetPositionCurrent(LONGLONG * pllPos)
{
if (m_pMS == NULL)
{
return FALSE;
}
if (m_dwCapability & AM_SEEKING_CanGetCurrentPos == 0 )
{
return FALSE;
}
return SUCCEEDED(m_pMS -> GetCurrentPosition(pllPos));
}
// ----------------------------------------------------------------------
// Description:
// This method sets current positions
//
// Parameters:
// llPos:[in]Start position if stopped, or position from which to continue if paused.
// -----------------------------------------------------------------------
BOOL CMedia::SetPositionCurrent(LONGLONG llPos)
{
if (m_pMS == NULL)
{
return FALSE;
}
LONGLONG llCur = 0 ;
if (GetPositionCurrent( & llCur) == TRUE)
{
if ((llCur > llPos) && (m_dwCapability & AM_SEEKING_CanSeekBackwards == 0 ))
{
return FALSE;
}
else if ((llCur < llPos) && (m_dwCapability & AM_SEEKING_CanSeekForwards == 0 ))
{
return FALSE;
}
else if (llCur == llPos)
{
// It's the current positon, needn't set
return TRUE;
}
}
else if ((m_dwCapability & AM_SEEKING_CanSeekBackwards == 0 ) || (m_dwCapability & AM_SEEKING_CanSeekForwards == 0 ))
{
return FALSE;
}
return SUCCEEDED(m_pMS -> SetPositions( & llPos,AM_SEEKING_AbsolutePositioning,NULL,AM_SEEKING_NoPositioning));
}
// ----------------------------------------------------------------------
// Description:
// This method get current display mode
//
// ----------------------------------------------------------------------
DISPLAYMODE CMedia::GetDisplayMode()
{
return m_DispMode;
}